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 — not Api-Key or 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-After response 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 — Message instead of message
  • Missing the required type field 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_facts if you only need a handful of facts
  • Pass a stable conversation_id for 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_URL is set incorrectly
  • Network or firewall blocking the connection from the console server
  • /readyz returns 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.

The V6 API does not accept tenant_id in any request payload. This is a security design — the API key determines the tenant, preventing accidental cross-tenant writes.

Still stuck?