Troubleshooting
Common issues, error codes, and debugging strategies for CLAIV Memory.
Recall returns empty answer_facts
If recall returns empty answer_facts and llm_context.text is blank, check these common causes:
1. Enrichment not complete. After /v6/ingest, the background pipeline takes 1–5 s to extract facts. Calling recall immediately after ingest may return empty results. In production this is rarely an issue — recall happens on the next user turn, not immediately after ingest.
2. Wrong user_id. The user_id is case-sensitive. User-123 and user-123 are different users. Make sure it exactly matches the one used during ingest.
3. Low-utility messages. Very short or generic messages ("OK", "thanks") contain no extractable facts. The Gate step filters them out and no facts are stored.
4. Check routing.mode. Inspect the routing object in the recall response. If routing.mode is broad and routing.predicates is empty, try making your query more specific.
401 Unauthorized
The API key in your Authorization header is missing, invalid, or revoked.
Checklist:
- Header format must be
Authorization: Bearer YOUR_KEY— notApi-Keyor any other format - Verify the key has not been revoked in the console under API Keys
- Check for leading/trailing whitespace in the key value
- Confirm the key belongs to the correct project (tenant)
429 Rate Limited
You've exceeded the per-minute rate limit for the endpoint. This is separate from the monthly quota.
Steps:
- Check the
Retry-Afterresponse header — it gives the seconds to wait before retrying - Implement exponential back-off with jitter (initial 1 s, max 30 s, ±500 ms jitter)
- Batch ingest calls if you are sending many events at once
429 Quota Exceeded
You've exhausted your plan's monthly ingest quota.
Steps to resolve:
- Check current usage via
GET /v1/usage/summary - Quotas reset on the 1st of each billing month
- Upgrade your plan for a higher quota or overage billing
{
"error": {
"code": "quota_exceeded",
"message": "Monthly ingest limit exceeded",
"request_id": "req_abc123",
"details": {
"plan": "free",
"reset_date": "2026-04-01T00:00:00Z",
"usage": { "ingest_events": 200, "limit": 200 }
}
}
}400 Bad Request — "Invalid type"
The type field must be one of: message, tool_call, or app_event.
Common mistakes:
- Using old V5 type names —
fact,loop,episode,chunk - Using uppercase —
Messageinstead ofmessage - Missing the required
typefield entirely
deduped: true unexpectedly
CLAIV detected that this event is a duplicate. A byte-identical message was already stored within the deduplication window for the same user_id.
This is normal behaviour for retry logic — it prevents double-enrichment. If you believe it is a false positive, check that the content differs sufficiently from recently ingested messages for the same user.
If you are ingesting the same message intentionally (e.g. backfill), use a unique idempotency_key to bypass deduplication.
High recall latency
Recall runs predicate match, vector similarity, keyword, and temporal search channels in parallel, then synthesizes the result with an LLM. Latency typically increases with stored fact volume and query ambiguity.
Optimisation tips:
- Use a specific, focused query — narrow queries produce faster, higher-quality results than vague ones
- Reduce result limits with
limits.answer_factsif you only need a handful of facts - Pass a stable
conversation_idfor conversation-scoped weighting (omit for global cross-chat memory) - Check the Usage tab's endpoint breakdown for latency percentile trends
Console: Test Connection fails
The Test Connection feature checks /healthz and /readyz on your CLAIV Memory backend.
Common causes:
- Backend is not running or not reachable at the configured URL
CLAIV_MEMORY_API_BASE_URLis set incorrectly- Network or firewall blocking the connection from the console server
/readyzreturns 503 when PostgreSQL or Redis is down
Ingest returns 400 — tenant_id not allowed
You are including a tenant_id field in your request payload. This is not allowed — the tenant is inferred automatically from your API key. Remove tenant_id from the request body entirely.
tenant_id in any request payload. This is a security design — the API key determines the tenant, preventing accidental cross-tenant writes.