headroomlabs-ai/headroom · error · MagikaDetectorError
magika session lock poisoned
Error message
magika session lock poisoned
What it means
After content-decoding, the body bytes could not be decoded as UTF-8 (helpers.py:2515, in the bytes-less JSON body reader). This means the decoded payload is binary or in another charset — JSON request bodies must be UTF-8 per RFC 8259. The message hints at compression because an undecoded compressed body is the most common cause: a client compressed the payload but sent no (or an 'identity') Content-Encoding header.
Source
Thrown at crates/headroom-core/src/transforms/magika_detector.rs:324
#[derive(Debug, Error)]
pub enum MagikaDetectorError {
/// One-time session initialization failed (model load, ONNX init).
/// Once we hit this, every subsequent call also fails — there is no
/// retry path here. The router should surface and stop.
#[error("magika session init failed: {0}")]
Init(String),
/// Inference call failed for this input. Usually transient; future
/// calls may succeed. The error message is the magika-side text;
/// we don't try to wrap it.
#[error("magika inference failed: {0}")]
Inference(String),
/// Singleton lock was poisoned (a previous holder panicked while
/// holding it). The detector is unusable until the process
/// restarts. We don't auto-recover — a panicked detector means
/// something is corrupt and continuing would mask it.
#[error("magika session lock poisoned")]
Poisoned,
}
/// One-process singleton holding the magika session. Lazily
/// initialized on first call to [`magika_detect`].
///
/// `Mutex<Result<Session, ...>>` rather than `Result<Mutex<Session>>`
/// so init failure is recorded once and replayed cheaply on every
/// subsequent call (no re-attempting the load — if the model file is
/// missing or ort can't init, retrying just wastes cycles).
static MAGIKA_SESSION: OnceLock<Mutex<Result<Session, String>>> = OnceLock::new();
/// Default cap on magika ONNX session init.
///
/// On some platforms `Session::new()` can hang indefinitely instead of
/// returning an error. Root-caused on Windows: with `ort-load-dynamic`
/// (Windows-gated in `Cargo.toml`), the bare `LoadLibrary("onnxruntime.dll")`
/// search resolves to `C:\Windows\System32\onnxruntime.dll` — the Windows MLView on GitHub (pinned to 322425c43b)
Solutions
- If the body is compressed, set the matching Content-Encoding header so the proxy decompresses it first
- Serialize JSON with ensure_ascii and UTF-8: json.dumps(obj).encode('utf-8')
- Send Content-Type: application/json; charset=utf-8 and verify the payload with a hex dump of the first bytes
Example fix
# before: compressed body, no header
requests.post(url, data=gzip.compress(json.dumps(payload).encode()))
# after
requests.post(url, data=gzip.compress(json.dumps(payload).encode()), headers={"Content-Encoding": "gzip"}) Defensive patterns
Strategy: try-catch
Validate before calling
raw.decode("utf-8") # client-side pre-flight; if this fails, fix encoding or header Try / catch
try:
payload = await _read_json_body(request)
except ValueError as exc:
return JSONResponse({"error": {"type": "invalid_request_error", "message": str(exc)}}, status_code=400) Prevention
- Always send Content-Encoding when the body is compressed
- Encode JSON with .encode('utf-8'), never platform-default charsets
When it happens
Trigger: POSTing a gzip/zstd/brotli-compressed JSON body without a Content-Encoding header; sending JSON serialized as UTF-16 or Latin-1; binary garbage reaching the JSON route.
Common situations: Middleware that compresses bodies but strips headers; clients that pre-compress with no header; locale-sensitive serializers producing non-UTF-8 bytes.
Related errors
- could not read pipeline config file: {0}
- ccr sqlite backend init failed: {0}
- ccr redis backend init failed: {0}
- ccr backend `{backend}` is not compiled in; rebuild with `--
- failed to load tokenizer for `{name}`: {source}
AI-assisted analysis of headroomlabs-ai/headroom@322425c43b (2026-08-15).
Data as JSON: /api/errors/e320276b517f1e69.
Report an issue: GitHub.