One flag, two incompatible brotli streams
Correction, 2026-07-31. This post originally
ran under the title "The brotli archive that could only be opened on the
machine that made it" and claimed such an archive needs the creating
machine's core count passed back to open. That was wrong. Re-testing
showed -mmt is a boolean mode switch on decode — the
value is ignored, so any -mmt reads the stream and the
archives are not machine-specific. The corrected mechanism is below; the
upstream
report has been corrected too. The failure mode is still real, just less
dire — and considerably cheaper to work around.
Septima is a small thing: a GTK front-end that drives the 7zz
binary from 7-Zip ZS. It
doesn't reimplement compression — it builds the right command line and reads
back what 7zz prints. That thinness is the whole design. It also
means Septima inherits 7zz's sharp edges — and, if you're paying
attention, catches them.
This is the story of one that would have quietly shipped unreadable archives to users, and how a single failing test caught it.
The trigger
In v0.3.0 we added Brotli, LZ4, LZ5 and Lizard as tar
post-compressors — so you can make a real .tar.br in one gesture.
Building the next feature (raw single-file streams), I wrote a
round-trip test: compress a blob, extract it, assert the bytes come back
identical. Every codec passed. Then brotli failed.
Isolating it
First guess: the compression level. I swept brotli levels 0–11 — all fine.
So not the level. Same file, same everything, and yet the test built a
.tar.br that 7zz itself refused to read:
7zz t out.tar.br
# ERROR: E_FAIL : Unspecified error
The difference between my passing manual test and the failing automated one
turned out to be a single flag the app always added: -mmt
(multithreading, set to the CPU count). Drop it, and the archive is fine. Add
it — any value, even -mmt=1 — and 7zz can no
longer read its own output.
It isn't corruption — it's two formats
"Unreadable" sounded like corruption, but the data was intact.
-mmt selects between two different stream formats: the
multithreaded chain, and plain brotli. Whichever one you wrote, you have to ask
for the same one back.
The trap is that -mmt means opposite things on the two sides.
On compress it's a thread count. On decompress it's a boolean
format selector, and the number is ignored entirely:
# created with -mmt4
7zz t mt4.br # ERROR: E_FAIL
7zz t -mmt=1 mt4.br # Everything is Ok
7zz t -mmt=2 mt4.br # Everything is Ok
7zz t -mmt=32 mt4.br # Everything is Ok
# created without -mmt
7zz t st.br # Everything is Ok
7zz t -mmt=1 st.br # ERROR: E_FAIL
Stated plainly, with -mmt=off behaving like the default and
-mmt=on like any -mmt=N:
| decode flag | mt stream | plain stream |
|---|---|---|
-mmt=off (or nothing) | E_FAIL | Ok |
-mmt=on (or any N) | Ok | E_FAIL |
A stream created with -mmt12 extracts byte-identical using
-mmt=2. So this is one bit of information — and brotli has
no
header block to record it in, which is exactly why 7zz can't
just detect it. You get a bare E_FAIL with no hint that a flag
would fix it.
The inversion. The behaviour flips by
context. Brotli inside a 7z container (-m0=brotli) works
fine with threads — so Septima's shipped 7z-brotli was never affected.
It's only the standalone -tbrotli stream (which
tar → brotli and raw .br both use) that splits into
two formats. Same codec, opposite thread behaviour.
The fix, write side
A single-threaded standard .br is portable and reads anywhere —
including with plain brotli, outside 7-Zip entirely. So the fix is
to omit -mmt for the -tbrotli path,
while keeping threads for 7z-container brotli, where they're both correct and
useful:
// engine: build the -m* args
if let Some(threads) = self.threads {
if self.format != "brotli" { // the standalone -tbrotli case
args.push(format!("-mmt={threads}"));
}
}
Hunting it also surfaced a second, quieter bug from the same v0.3.0 work:
the code that recognises "this is a compressed tar, browse inside it" had never
learned .tar.br / .tar.lz5 / .tar.liz —
so those archives, creatable since v0.3.0, couldn't be transparently opened.
Fixed in the same pass.
The fix, read side
Not producing the trap is only half the job. Users open archives they didn't
create — an mt-brotli .tar.br from a colleague, a script, or
7-Zip ZS on Windows. Septima passed no -mmt when extracting, so
those failed with the same opaque E_FAIL.
Because there are exactly two modes and the value is irrelevant, the recovery is deterministic — no sniffing, no searching a space of thread counts, no heuristic that can be wrong:
// extract/test a brotli-family target
if run(args).failed_with_efail() {
run(args + ["-mmt=on"]); // flip to the other of the two formats
}
One retry, only on the failure path, only for brotli. That covers every mt-brotli stream in existence, whatever machine wrote it.
Why a thin wrapper earns its keep
It would be easy to dismiss "just shells out to 7zz" as barely
a project. But the thinness is exactly why this got caught: Septima's job is to
build correct command lines and verify what comes back, and its test suite
round-trips real archives through the real binary. That's what turned a silent,
flag-dependent failure into a red test on a Tuesday — before a single user made
an unopenable .tar.br.
It's also why the correction at the top of this post exists. The first
version of this write-up got the mechanism wrong in a way that sounded
worse than reality, and the same wrong claim went upstream. Re-running the
matrix — every decode flag against both stream types, extraction and not just
t — is what settled it. Test the thing; don't reason about it from
one data point.
Update, 10 August 2026: both fixes shipped in v0.4.0,
along with the rest of the 7zz CLI-parity work — flatpak
update if you're on the signed repo. Any .br or
.tar.br written by v0.3.0 is still corrupt and can't be repaired;
recreate those.
Upstream went further than the workaround described here. After testing
the detection design on Linux and reporting a follow-on regression,
7-Zip ZS #538
settled on trying the single-threaded decode first and treating
-mmt=off as the deliberate opt-in for the multithreaded format
inside a .7z. Septima now retries with that flag on its own, so
archives made elsewhere with raw brotli in a container open too.