Errors & Status Codes
Mnemexa uses standard HTTP status codes. Most error responses follow FastAPI’s default shape — a single detail field. A few endpoints attach extra structured fields for programmatic handling.
Default response shape
{
"detail": "Missing or invalid Authorization header"
}
That’s it — a single string. Use the HTTP status code as the primary discriminator. Use detail to surface a user-readable message.
Structured errors
Some endpoints return additional fields alongside detail for cases where machine-readable handling matters:
{
"error": "pii_rejected",
"code": "pii_rejected",
"detail": "Submitted memory contains sensitive data and cannot be stored."
}
When error / code are present, treat them as the authoritative machine-readable reason. When only detail is present, dispatch on the HTTP status code.
Status codes
| Status | When you’ll see it | Recommended action |
|---|---|---|
200 | Success. | — |
400 | Malformed request — invalid Content-Length, non-JSON body, oversize payload (for events). | Fix the request before retrying. |
401 | Missing Authorization header, malformed Bearer … syntax, empty key, or unknown key. | Verify the API key. Don’t retry until fixed. |
403 | Key is recognized but inactive (disabled), workspace deleted, client account suspended, or workspace suspended on a memory endpoint. | Inspect via status. Don’t retry until the underlying condition changes. |
413 | Payload exceeds the size cap (events: 256 KB). | Reduce payload size. |
422 | Pydantic validation failure on the request body, or structured error like pii_rejected. | Look at detail (and code if present). Don’t retry until fixed. |
429 | Rate limit exceeded, or plan unit limit reached for the current billing cycle. | Read Retry-After header. Back off. |
500 | Unexpected server error. | Retry with backoff. If persistent, escalate to support with the response body. |
502 / 503 / 504 | Transient upstream/network issue. | Retry with exponential backoff. SDK does this automatically. |
Distinguishing 429 reasons
429 can mean two different things:
- Per-minute rate limit — too many requests in a short window. Use
Retry-Afterto find out when to retry. - Plan unit limit — your workspace exhausted its monthly memory-write or memory-retrieve quota. Retrying won’t help; either upgrade the plan or wait for the next billing cycle. The
workspace_statuswill belimit_reachedif you check via status.
Both return 429 with Retry-After. To tell them apart, call status — if workspace_status is limit_reached, it’s a plan limit, not a rate limit.
What 403 means on different endpoints
| Endpoint | 403 means |
|---|---|
memory.store · memory.retrieve | Workspace suspended, workspace deleted, client account suspended, or API key disabled. |
optimize.health · status | API key disabled, workspace deleted, or client account suspended. Workspace suspended does not trigger 403 here — these endpoints work specifically so suspended workspaces can diagnose. |
Handling errors in Python
import mnemexa
client = mnemexa.Client()
try:
client.memory.store(text="…")
except mnemexa.AuthenticationError as exc:
# 401 — bad key. Fix config; don't retry.
print(exc.status_code, exc.detail)
except mnemexa.PermissionError as exc:
# 403 — workspace suspended or key disabled. Check status endpoint.
s = client.status()
print(f"workspace_status={s.workspace_status}")
except mnemexa.ValidationError as exc:
# 422 — request body or PII rejection. Inspect exc.body for the structured fields.
print(exc.body)
except mnemexa.RateLimitError as exc:
# 429 — back off for exc.retry_after seconds (could be per-min or plan limit)
time.sleep(exc.retry_after)
except mnemexa.ServiceUnavailableError:
# 5xx — the SDK already retried max_retries times. Escalate or fall back.
pass
Every error from the SDK exposes status_code, request_id, body, and detail. Include request_id in support escalations — it pins the failure to a single log line on Mnemexa’s side.
Request IDs
The Python SDK and MCP adapter both send X-BizX-Request-ID headers (a UUID) on every request. Mnemexa’s logs index by this ID, so quoting it in support tickets gets you to the relevant trace in seconds rather than minutes.
If you’re calling the REST API directly without the SDK, you can send your own X-BizX-Request-ID header to correlate. If you don’t, the server still generates an internal trace ID, but it’s harder to look up after the fact.
Never log the full Authorization header. Log request_id and status_code; the rest is supplemental.