ducaale/xh · error

unknown compression type

Error message

unknown compression type

What it means

CompressionType::from_str maps a Content-Encoding token to the tool's supported decoders (gzip, deflate, brotli, zstd). Any other token — even a valid but unimplemented encoding like 'compress' or 'identity' — returns this bare error.

Solutions

  1. Fix or disable the server/CDN header so it advertises a supported encoding (gzip, deflate, br, zstd)
  2. Set Accept-Encoding on your request to only supported values so the server doesn't pick an unknown one
  3. Check the decoder's build features (e.g. zstd may be optional) and rebuild with the needed feature

Example fix

// before (server sends Content-Encoding: compress)
curl -H 'Accept-Encoding: gzip, br' ...
// after
xh GET https://example.com Accept-Encoding:gzip, deflate, br
Defensive patterns

Strategy: validation

Validate before calling

const SUPPORTED: &[&str] = &["gzip", "x-gzip", "deflate", "br", "zstd"];
fn is_supported_encoding(token: &str) -> bool {
    SUPPORTED.contains(&token.trim().to_lowercase().as_str())
}

Try / catch

let ct = get_compression_type(&headers);
let decoder = match ct.map(CompressionType::from_str) {
    Some(Err(e)) => { eprintln!("{e}: falling back to identity"); None }
    other => other.ok().flatten(),
};

Prevention

When it happens

Trigger: Server responds with Content-Encoding: compress, x-compress, zstd when the binary was built without the zstd feature, or any custom/unrecognized token.

Common situations: Legacy servers using the historical 'compress' encoding, misconfigured servers advertising encodings they don't actually send, CDN injecting unusual Content-Encoding values, feature-flag differences between builds.

Related errors


AI-assisted analysis of ducaale/xh@2404aceecc (2026-09-13). Data as JSON: /api/errors/48cdb89c457fab12. Report an issue: GitHub.

Appendix: source

Thrown at src/decoder.rs:33

    Gzip,
    Deflate,
    Brotli,
    Zstd,
}

impl FromStr for CompressionType {
    type Err = anyhow::Error;
    fn from_str(value: &str) -> anyhow::Result<CompressionType> {
        match value {
            // RFC 2616 section 3.5:
            //   For compatibility with previous implementations of HTTP,
            //   applications SHOULD consider "x-gzip" and "x-compress" to be
            //   equivalent to "gzip" and "compress" respectively.
            "gzip" | "x-gzip" => Ok(CompressionType::Gzip),
            "deflate" => Ok(CompressionType::Deflate),
            "br" => Ok(CompressionType::Brotli),
            "zstd" => Ok(CompressionType::Zstd),
            _ => Err(anyhow::anyhow!("unknown compression type")),
        }
    }
}

// See https://github.com/seanmonstar/reqwest/blob/9bd4e90ec3401c2c5bc435c58954f3d52ab53e99/src/async_impl/decoder.rs#L150
pub fn get_compression_type(headers: &HeaderMap) -> Option<CompressionType> {
    let mut compression_type = headers
        .get_all(CONTENT_ENCODING)
        .iter()
        .find_map(|value| value.to_str().ok().and_then(|value| value.parse().ok()));

    if compression_type.is_none() {
        compression_type = headers
            .get_all(TRANSFER_ENCODING)
            .iter()
            .find_map(|value| value.to_str().ok().and_then(|value| value.parse().ok()));
    }

View on GitHub (pinned to 2404aceecc)