headroomlabs-ai/headroom · error · RecommendationsError
recommendations file not found: {0}
Error message
recommendations file not found: {0} What it means
The non-object-JSON rejection in _read_json_body_with_bytes (helpers.py:2551), the shared reader behind the Anthropic, OpenAI, and Bedrock request paths. The body is valid JSON but its root is not an object (list/str/int/bool/null), and these APIs require an object.
Source
Thrown at crates/headroom-core/src/transforms/recommendations.rs:252
/// Module-level convenience: look up a recommendation in the global
/// store. PR-F3 will wire this into `dispatch_compressor`. PR-B5 only
/// exposes the API surface.
pub fn get(
auth_mode: AuthMode,
model: &str,
structure_hash: &str,
) -> Option<&'static Recommendation> {
load_default().lookup(auth_mode, model, structure_hash)
}
/// Errors surfaced by the loader. Marked non-exhaustive so we can add
/// future variants without breaking callers.
#[derive(Debug, thiserror::Error)]
#[non_exhaustive]
pub enum RecommendationsError {
/// File doesn't exist on disk.
#[error("recommendations file not found: {0}")]
Missing(PathBuf),
/// Filesystem error other than NotFound.
#[error("recommendations IO error at {path}: {source}")]
Io {
path: PathBuf,
#[source]
source: std::io::Error,
},
/// TOML parse failure (typed wrapper for ergonomics).
#[error("recommendations TOML parse error: {0}")]
Parse(#[from] toml::de::Error),
}
#[cfg(test)]
mod tests {
use super::*;
fn sample_toml() -> &'static str {View on GitHub (pinned to 322425c43b)
Solutions
- Send a top-level JSON object with the expected schema keys
- Guard client-side: assert isinstance(json.loads(text), dict)
- Remove wrapping middleware that envelopes payloads in arrays
Example fix
// before (js)
fetch(url, {body: JSON.stringify([msg])})
// after
fetch(url, {body: JSON.stringify({model, messages: [msg]})}) Defensive patterns
Strategy: type-guard
Validate before calling
assert isinstance(payload, dict), f"request must be a JSON object, got {type(payload).__name__}" Type guard
def is_request_object(v: object) -> TypeGuard[dict]:
return isinstance(v, dict) Try / catch
try:
result, raw = await _read_json_body_with_bytes(request)
except ValueError as exc:
return JSONResponse({"error": str(exc)}, status_code=400) Prevention
- Don't reuse batch-API wrappers against single-request endpoints
- Check for double json.dumps in client code
When it happens
Trigger: Sending an array-wrapped or scalar JSON body to any main proxied chat route (Anthropic /v1/messages, OpenAI-compatible /v1/chat/completions, Bedrock translation path).
Common situations: Batch-style clients, double-serialized strings, or fixture reuse from other APIs hitting the primary proxy paths.
Related errors
- invalid pipeline config TOML: {0}
- items_json must be JSON: {e}
- doc_json must be JSON: {e}
- ccr sqlite backend init failed: {0}
- ccr redis backend init failed: {0}
AI-assisted analysis of headroomlabs-ai/headroom@322425c43b (2026-08-15).
Data as JSON: /api/errors/3e0256af5fcb8aae.
Report an issue: GitHub.