denoland/deno · error · TypeError
brotli decompression failed
Error message
brotli decompression failed
What it means
Deno's DecompressionStream for 'brotli': when the stream finishes (writer closed), the underlying brotli decoder is finalized via into_inner(); if the compressed data ended mid-stream (incomplete brotli stream) or is corrupt, finalization fails and the stream errors with ErrorKind::InvalidData. Note the wrapper suppresses errors when report_errors is false, in which case the symptom is a silently empty/truncated result instead of this error.
Source
Thrown at ext/web/compression.rs:289
.take()
.ok_or(CompressionError::ResourceClosed)?;
let out = match inner {
Inner::DeflateDecoder(d) => {
d.finish().map_err(CompressionError::IoTypeError)
}
Inner::DeflateEncoder(d) => {
d.finish().map_err(CompressionError::IoTypeError)
}
Inner::DeflateRawDecoder(d) => {
d.finish().map_err(CompressionError::IoTypeError)
}
Inner::DeflateRawEncoder(d) => {
d.finish().map_err(CompressionError::IoTypeError)
}
Inner::GzDecoder(d) => d.finish().map_err(CompressionError::IoTypeError),
Inner::GzEncoder(d) => d.finish().map_err(CompressionError::IoTypeError),
Inner::BrotliDecoder(d) => d.into_inner().map_err(|_| {
CompressionError::IoTypeError(std::io::Error::new(
std::io::ErrorKind::InvalidData,
"brotli decompression failed",
))
}),
Inner::BrotliEncoder(d) => d.finish(),
};
match out {
Err(err) => {
if report_errors {
Err(err)
} else {
Ok(Vec::with_capacity(0).into())
}
}
Ok(out) => Ok(out.into()),
}
}
View on GitHub (pinned to a961cdec3b)
Solutions
- Verify the source integrity before decompressing (Content-Length match, checksum/hash of the .br payload).
- Re-download or regenerate the brotli artifact from a trusted source.
- Catch the stream error explicitly and report which asset failed instead of propagating mid-pipe.
- If responses come from your own server, ensure it does not close the body early (check compression middleware ordering).
Example fix
// before
const text = await new Response(fileStream.pipeThrough(new DecompressionStream("brotli"))).text(); // truncated .br -> InvalidData (or silent empty)
// after
const bytes = new Uint8Array(await new Response(fileStream).arrayBuffer());
if (bytes.length < 8) throw new Error("brotli payload implausibly small — likely truncated");
try {
const text = await new Response(new Blob([bytes]).stream().pipeThrough(new DecompressionStream("brotli"))).text();
} catch (e) {
throw new Error(`corrupt brotli asset (${bytes.length} bytes): ${e.message}`);
} Defensive patterns
Strategy: try-catch
Validate before calling
const res = await fetch(url);
const enc = res.headers.get("content-encoding");
if (enc && enc !== "br" && enc !== "gzip" && enc !== "deflate") throw new Error(`unsupported content-encoding: ${enc}`);
if (res.headers.has("content-length") && Number(res.headers.get("content-length")) < 4) throw new Error("body too small to be a valid compressed stream"); Try / catch
try { text = await decompress(bytes); } catch (e) { if (/brotli decompression failed/.test(String(e))) throw new Error(`corrupt/truncated brotli payload for ${url} — re-fetch the source`); throw e; } Prevention
- Verify sizes/checksums of downloaded .br assets before decompressing.
- Validate Content-Encoding matches what you actually requested.
- Remember error suppression: a silently empty result can be the same root cause as this error.
When it happens
Trigger: Piping truncated or corrupt brotli data through DecompressionStream('brotli') and then closing the writer: cut-off downloads, files truncated by disk limits, or upstream errors where Content-Length promised more bytes than the compressed stream contained.
Common situations: Decompressing .br assets whose download was interrupted; proxy-truncated responses; concatenating or hand-editing brotli files; precompressed artifacts produced by a different/older brotli version.
Related errors
- brotli compression failed
- ERR_INVALID_ARG_TYPE
- ERR_INVALID_ARG_VALUE
- ERR_INVALID_ARG_VALUE
- ERR_ARG_NOT_ITERABLE
AI-assisted analysis of denoland/deno@a961cdec3b (2026-08-20).
Data as JSON: /api/errors/5110631b803c743d.
Report an issue: GitHub.