oven-sh/bun · error · TypeError

CompressionFailed

CompressionFailed

Error message

CompressionFailed

What it means

Compressing a buffered fetch request body failed at the codec level (src/http/compress_body.rs — construction sites at :145, :168, :208, :221, :226, :238). This is the automatic request-body compression behind `fetch(url, { compress: ... })`: gzip/deflate go through libdeflate with a zlib streaming fallback, brotli/zstd use one-shot encoders. Any encoder init failure, bad zlib return code, zstd compress_bound error, or failed one-shot encode maps to CompressionFailed and fails the request.

Source

Thrown at src/http/error.rs:4

#[allow(non_camel_case_types)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, thiserror::Error)]
pub enum Error {
    #[error("CompressionFailed")]
    CompressionFailed,
    #[error("Aborted")]
    Aborted,
    #[error("WriteFailed")]
    WriteFailed,
    #[error("HTTP2RefusedStream")]
    HTTP2RefusedStream,
    #[error("HTTP2ContentLengthMismatch")]
    HTTP2ContentLengthMismatch,
    #[error("HTTP2FrameSizeError")]
    HTTP2FrameSizeError,
    #[error("HTTP2ProtocolError")]
    HTTP2ProtocolError,
    #[error("HTTP2FlowControlError")]
    HTTP2FlowControlError,
    #[error("HTTP2EnhanceYourCalm")]
    HTTP2EnhanceYourCalm,
    #[error("HTTP2HeaderListTooLarge")]

View on GitHub (pinned to 8c5296ac45)

Solutions

  1. Drop the custom `level` and use `compress: true` or `compress: 'gzip'` — defaults are pre-validated per codec (deflate 6, brotli 6, zstd 3).
  2. Clamp the level yourself per encoding: deflate/gzip 0-9, brotli 0-11, zstd 1-22 minus extreme values.
  3. For multi-GB bodies, split the upload or compress manually with Bun.gzip/Bun.deflateSync in chunks instead of request-body compression.
  4. Catch the fetch rejection and retry uncompressed if compression is optional for the server.

Example fix

// before
await fetch(url, { method: 'POST', body: bigJson, compress: { type: 'gzip', level: 11 } }); // zlib max is 9
// after
await fetch(url, { method: 'POST', body: bigJson, compress: { type: 'gzip', level: Math.min(9, level) } });
// or simply
await fetch(url, { method: 'POST', body: bigJson, compress: true });
Defensive patterns

Strategy: try-catch

Validate before calling

const LEVELS = { gzip: [0, 9], deflate: [0, 9], br: [0, 11], zstd: [1, 22] };
function validCompress(opt) {
  if (opt === true || typeof opt === 'string') return true;
  const enc = opt.type ?? opt.encoding;
  const [lo, hi] = LEVELS[enc];
  return opt.level === undefined || (opt.level >= lo && opt.level <= hi);
}
if (!validCompress(opts.compress)) opts.compress = true; // fall back to defaults

Try / catch

try {
  const res = await fetch(url, { method: 'POST', body, compress });
} catch (err) {
  if (String(err.message).includes('CompressionFailed')) {
    return fetch(url, { method: 'POST', body }); // retry uncompressed
  }
  throw err;
}

Prevention

When it happens

Trigger: Calling fetch with `compress: { encoding: 'gzip'|'deflate'|'br'|'zstd', level }` where level is outside the codec's accepted range (zlib path clamps to 0..=9, but a wildly invalid value or mismatched encoding/level combos can still fail encoder creation), or the input triggers a compress_bound overflow (multi-GB zstd bodies). Buffered (string/Bytes) bodies only — streams skip compression.

Common situations: Porting Node code with numeric compression levels tuned per codec (brotli 11 passed where zlib 9 max); sending very large (>2-4GB) JSON payloads with compress on; version skew where a codec level enum changed meaning.

Related errors


AI-assisted analysis of oven-sh/bun@8c5296ac45 (2026-08-16). Data as JSON: /api/errors/78a40a24a9f2b7cb. Report an issue: GitHub.