headroomlabs-ai/headroom · error · ConfigError

could not read pipeline config file: {0}

Error message

could not read pipeline config file: {0}

What it means

Same UTF-8 check as error 307, but raised in _read_json_body_with_bytes (helpers.py:2547) — the shared reader used by the Anthropic, OpenAI, and Bedrock handlers that also returns the post-decode bytes for passthrough decisions. The body bytes after content-decoding are not valid UTF-8, so JSON text decoding is impossible.

Source

Thrown at crates/headroom-core/src/transforms/pipeline/config.rs:223

    pub min_segments: usize,
    pub target_ratio: f64,
}

/// Knobs for the [`crate::transforms::pipeline::offloads::DiffNoise`]
/// offload. Lockfile suffixes are matched against the new-file path
/// at the end of each `diff --git` header.
#[derive(Debug, Clone, Deserialize)]
pub struct DiffNoiseConfig {
    pub min_lines: usize,
    pub lockfile_suffixes: Vec<String>,
    pub drop_whitespace_only_hunks: bool,
}

#[derive(Debug, thiserror::Error)]
pub enum ConfigError {
    #[error("invalid pipeline config TOML: {0}")]
    Parse(#[from] toml::de::Error),
    #[error("could not read pipeline config file: {0}")]
    Io(std::io::Error),
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn from_default_str_does_not_panic() {
        // Embedded TOML must always deserialize cleanly.
        let _ = PipelineConfig::from_default_str();
    }

    #[test]
    fn defaults_match_documented_thresholds() {
        let cfg = PipelineConfig::default();
        assert_eq!(cfg.pipeline.reformat_target_ratio, 0.5);
        assert_eq!(cfg.pipeline.bloat_threshold, 0.5);

View on GitHub (pinned to 322425c43b)

Solutions

  1. Set the correct Content-Encoding header for compressed bodies
  2. Encode JSON as UTF-8 before sending
  3. Inspect the first bytes of the body: gzip is 1f 8b, zlib is 78 xx, zstd is 28 b5 2f fd — if you see these, the header was lost

Example fix

# before: zstd body, no header
requests.post(url, data=zstandard.compress(body))

# after
requests.post(url, data=zstandard.compress(body), headers={"Content-Encoding": "zstd"})
Defensive patterns

Strategy: try-catch

Validate before calling

raw.decode("utf-8")  # verify before sending; check for magic bytes if compressed

Try / catch

try:
    result, raw = await _read_json_body_with_bytes(request)
except ValueError as exc:
    return JSONResponse({"error": {"type": "invalid_request_error", "message": str(exc)}}, status_code=400)

Prevention

When it happens

Trigger: Any proxied /v1/messages, OpenAI-compatible, or Bedrock-routed request whose (decompressed) bytes fail UTF-8 decoding: compressed body without a Content-Encoding header, or a non-UTF-8 charset payload.

Common situations: Compressed bodies with stripped headers on the main chat-completion paths; gateway re-encoding; clients on Windows producing UTF-16 JSON.

Related errors


AI-assisted analysis of headroomlabs-ai/headroom@322425c43b (2026-08-15). Data as JSON: /api/errors/b1b72ccd9f4be591. Report an issue: GitHub.