headroomlabs-ai/headroom · error · HTTPException
Invalid tool call or not a {CCR_TOOL_NAME} call
Error message
Invalid tool call or not a {CCR_TOOL_NAME} call What it means
POST /v1/retrieve/tool_call parses the submitted tool_call for the given provider (default anthropic) and returns HTTP 400 when parsing yields no hash — the payload is malformed or is not a headroom_retrieve (CCR_TOOL_NAME) call. This is request-shape validation, not a store miss.
Source
Thrown at headroom/proxy/server.py:4999
"provider": "openai"
}
Response:
{
"tool_result": {...}, # Formatted for the provider
"success": true,
"data": {...} # Raw retrieval data
}
"""
data = await request.json()
tool_call = data.get("tool_call", {})
provider = data.get("provider", "anthropic")
# Parse the tool call
hash_key = parse_tool_call(tool_call, provider)
if hash_key is None:
raise HTTPException(
status_code=400, detail=f"Invalid tool call or not a {CCR_TOOL_NAME} call"
)
# Perform retrieval
store = get_compression_store()
entry_status = store.get_entry_status(hash_key, clean_expired=True)
if entry_status["status"] != "available":
retrieval_data = {
"error": format_retrieval_miss_detail(entry_status),
"hash": hash_key,
"status": entry_status["status"],
"ttl_seconds": entry_status.get("ttl_seconds", entry_status["default_ttl_seconds"]),
}
else:
# Retrieval is by hash: always return the full original content.
entry = store.retrieve(hash_key)
if entry:View on GitHub (pinned to 322425c43b)
Solutions
- Send only headroom_retrieve tool calls to this endpoint.
- Match the provider field to the actual payload ('anthropic', 'openai', ...).
- Ensure the tool-call arguments include the compression hash.
- For raw hashes, use POST /v1/retrieve with {"hash": ...} instead.
Example fix
# before
{"tool_call": {"name": "web_search", "arguments": {}}, "provider": "anthropic"}
# after
{"tool_call": {"name": "headroom_retrieve", "arguments": {"hash": "abc123"}}, "provider": "anthropic"} Defensive patterns
Strategy: validation
Validate before calling
def is_retrieve_call(tool_call: dict) -> bool:
return tool_call.get("name") == "headroom_retrieve" and bool(
(tool_call.get("arguments") or {}).get("hash")
) Type guard
def is_retrieve_call(tc: dict) -> bool:
name = tc.get("name") or tc.get("function", {}).get("name")
return name == "headroom_retrieve" Try / catch
resp = await client.post("/v1/retrieve/tool_call", json=payload)
if resp.status_code == 400:
route_elsewhere(payload) # not a headroom_retrieve call; don't retry Prevention
- Filter tool calls by name before hitting the endpoint.
- Keep the provider field consistent with the payload format.
When it happens
Trigger: Posting a tool_call for a different tool name, missing the hash argument, wrong provider string so the parse format mismatches, or an arbitrary JSON object.
Common situations: Agent frameworks forwarding every LLM tool call indiscriminately; provider field not matching the actual tool_call format; schema drift in tool-call JSON.
Related errors
- {BODY_TOO_LARGE_STATUS_ENV} must be an integer, got {raw!r}
- {BODY_TOO_LARGE_STATUS_ENV} must be a 4xx/5xx status, got {v
- hash required
- invalid pipeline config TOML: {0}
- recommendations file not found: {0}
AI-assisted analysis of headroomlabs-ai/headroom@322425c43b (2026-08-15).
Data as JSON: /api/errors/1aaf11cf4e55af19.
Report an issue: GitHub.