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.

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)

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.