denoland/deno · error · TypeError

brotli compression failed

Error message

brotli compression failed

What it means

Deno's Web Streams CompressionStream implementation for the 'brotli' format: each write/flush runs through BrotliEncoderCompressStream, and if the native encoder returns failure (ok == false), the stream errors with ErrorKind::InvalidData and this message. Encoder failures are rare and usually indicate invalid stream state or memory pressure rather than bad input data.

Solutions

  1. Confirm the format is exactly 'brotli' (not 'br', 'gzip', 'deflate', or 'deflate-raw').
  2. Stream in modest chunks via pipeThrough(new CompressionStream('brotli')) instead of one huge write(), letting backpressure work.
  3. Catch the stream error and fall back to identity or gzip/deflate compression so the response still ships.
  4. Update Deno — native encoder fixes land in runtime updates.

Example fix

// before
const out = await new Response(blob.pipeThrough(new CompressionStream("brotli")).catch(() => blob)).arrayBuffer(); // unhandled mid-stream error

// after
async function compressBrotli(blob) {
  try {
    return { body: blob.pipeThrough(new CompressionStream("brotli")), encoding: "br" };
  } catch {
    return { body: blob, encoding: "identity" }; // graceful fallback
  }
}
Defensive patterns

Strategy: fallback

Validate before calling

const VALID = new Set(["gzip", "deflate", "deflate-raw", "brotli"]);
if (!VALID.has(format)) throw new Error(`CompressionStream format must be one of ${[...VALID]}, got ${format}`);

Try / catch

try { return await compressWith(new CompressionStream("brotli"), bytes); } catch (e) { if (/brotli compression failed/.test(String(e))) return bytes; /* identity fallback */ throw e; }

Prevention

When it happens

Trigger: new CompressionStream('brotli') whose writer hits a native encoder failure during write(), flush(), or close() — e.g. corrupted encoder state after misuse of the stream, extremely large single-shot buffers, or a native brotli bug triggered by specific chunk boundaries.

Common situations: Server-side response compression pipelines built on CompressionStream('brotli'); piping very large files through a single write; version-specific encoder regressions; feeding the wrong format string ('br' instead of 'brotli' throws earlier, but near-misses confuse debugging).

Related errors


AI-assisted analysis of denoland/deno@a961cdec3b (2026-08-20). Data as JSON: /api/errors/2c678ad41d8af6ec. Report an issue: GitHub.

Appendix: source

Thrown at ext/web/compression.rs:107

    let mut output_offset = 0;
    let mut total_out = Some(0);

    loop {
      let mut available_out = output.len() - output_offset;
      let ok = self.stm.compress_stream(
        operation,
        &mut available_in,
        input,
        &mut input_offset,
        &mut available_out,
        &mut output,
        &mut output_offset,
        &mut total_out,
        &mut |_, _, _, _| (),
      );

      if !ok {
        return Err(CompressionError::IoTypeError(std::io::Error::new(
          std::io::ErrorKind::InvalidData,
          "brotli compression failed",
        )));
      }

      let done = match operation {
        BrotliEncoderOperation::BROTLI_OPERATION_FINISH => {
          self.stm.is_finished()
        }
        _ => available_in == 0 && !self.stm.has_more_output(),
      };

      if done {
        output.truncate(output_offset);
        return Ok(output);
      }

      if output_offset == output.len() {

View on GitHub (pinned to a961cdec3b)