headroomlabs-ai/headroom · error · CcrBackendInitError

ccr sqlite backend init failed: {0}

Error message

ccr sqlite backend init failed: {0}

What it means

The proxy received a request whose Content-Encoding header is 'zstd' or 'zstandard', but the optional 'zstandard' package is not installed in the environment. headroom lazily imports zstandard only when a zstd-compressed body actually arrives (helpers.py:2406), so the server starts fine and fails only on such requests. The ValueError is raised from the body-reading helper so callers can translate it into a clean 400 response.

Source

Thrown at crates/headroom-core/src/ccr/backends/mod.rs:68

        }
    }

    /// In-memory with library defaults. Useful in tests.
    pub fn in_memory_default() -> Self {
        Self::InMemory {
            capacity: crate::ccr::DEFAULT_CAPACITY,
            ttl_seconds: crate::ccr::DEFAULT_TTL.as_secs(),
        }
    }
}

/// Reasons `from_config` may fail. Each variant is loud and recoverable
/// at the proxy startup boundary — the operator is told exactly what
/// went wrong rather than silently degrading to in-memory.
#[derive(Debug, Error)]
pub enum CcrBackendInitError {
    /// SQLite open / schema-create failed.
    #[error("ccr sqlite backend init failed: {0}")]
    Sqlite(#[from] rusqlite::Error),
    /// Redis open / PING failed (the smoke-test in `RedisCcrStore::open`).
    #[cfg(feature = "redis")]
    #[error("ccr redis backend init failed: {0}")]
    Redis(::redis::RedisError),
    /// Operator selected a backend whose feature flag was not compiled
    /// in. Loud failure rather than silent fallback.
    #[error(
        "ccr backend `{backend}` is not compiled in; rebuild with `--features {feature}` \
         or pick a different backend"
    )]
    UnsupportedBackend {
        backend: &'static str,
        feature: &'static str,
    },
}

#[cfg(feature = "redis")]

View on GitHub (pinned to 322425c43b)

Solutions

  1. pip install zstandard (or add it to the deployment requirements/extra)
  2. Configure the client to stop sending Content-Encoding: zstd and send identity/gzip instead
  3. Catch the ValueError in your caller and return a 400 so the client learns the encoding is unsupported

Example fix

# before: client sends zstd
requests.post(url, data=zstandard.compress(payload), headers={"Content-Encoding": "zstd"})

# after: send identity (uncompressed)
requests.post(url, data=payload, headers={"Content-Encoding": "identity"})
Defensive patterns

Strategy: validation

Validate before calling

# Before sending: only advertise zstd when the server can decode it
import sys
if "zstandard" not in sys.modules:
    try:
        import zstandard  # noqa: F401
    except ImportError:
        headers.pop("Content-Encoding", None)  # fall back to identity

Try / catch

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

Prevention

When it happens

Trigger: A client sends POST /v1/messages (or any proxied route that reads the JSON body) with 'Content-Encoding: zstd' while 'zstandard' is absent from the Python environment. This happens when requests are made via HTTP libraries that transparently compress bodies (e.g. curl --compressed, some SDKs) or hand-rolled zstd-compressed JSON.

Common situations: Deploying headroom in a slim Docker image or minimal venv without the optional compression extras; a new client SDK version that starts using zstd by default; CI environments where only core requirements are installed.

Related errors


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