FishMem

Errors and idempotency

Stable error envelopes, permissions, request identity, and retry behavior.

Every non-2xx API response uses:

{
  "code": "INVALID_REQUEST",
  "message": "One of user_id, agent_id, run_id is required",
  "request_id": "req_...",
  "details": {}
}

details is optional. request_id is also sent as the x-request-id response header.

Common statuses

StatusExample codeMeaning
400INVALID_REQUEST, INVALID_CURSOR, IDEMPOTENCY_KEY_REQUIREDRequest cannot be executed
401INVALID_API_KEY, API_KEY_EXPIREDAuthentication failed
402INSUFFICIENT_CREDITSHosted project has no remaining credits
403INSUFFICIENT_PERMISSIONKey lacks memory:read, memory:write, or operations:read; memory permissions also govern source documents
404MEMORY_NOT_FOUND, DOCUMENT_NOT_FOUND, DOCUMENT_UPLOAD_NOT_FOUND, OPERATION_NOT_FOUNDResource is absent in the authenticated project
409IDEMPOTENCY_CONFLICT, VERSION_CONFLICT, DOCUMENT_UPLOAD_INCOMPLETE, DOCUMENT_UPLOAD_IMMUTABLE, DOCUMENT_UPLOAD_SIZE_MISMATCH, DOCUMENT_UPLOAD_CHECKSUM_MISMATCH, USAGE_RESERVATION_IN_PROGRESS, USAGE_CHARGE_CONFLICTRetry identity, immutable upload, Hosted charge, or optimistic version conflicts
413DOCUMENT_UPLOAD_TOO_LARGE, EXTRACTED_DOCUMENT_TOO_LARGE, DOCUMENT_PAGE_LIMIT_EXCEEDEDRaw file, extracted text, or page count exceeds a production fence
415UNSUPPORTED_DOCUMENT_MEDIA_TYPEFile upload declared an unsupported media type
429RATE_LIMITEDThe Cloudflare deployment's per-key request window is exhausted
500MEMORY_ENGINE_ERROREngine or provider operation failed

Provider messages are not a stable client contract. Branch on status and code, log request_id, and show message to an operator when appropriate.

Idempotency

FishMem Cloud requires Idempotency-Key for memory add/update/delete-by-id, direct document ingest/delete, and source-asset creation. Export and import require it on every deployment. Self-hosted deployments should send it for the same mutation paths.

  • same key + same command: the original operation/result is reused;
  • same key + different command: 409 IDEMPOTENCY_CONFLICT;
  • key length: 1200 non-whitespace characters.

The server does not need or want client-generated memory IDs. Use a stable business command identity such as customer-123-preference-v2.

Bulk delete is state-idempotent, but its deleted count describes that particular execution; do not use the count as a retry identity.

For file extraction, repeat create with the same key and command to recover the same source asset, then safely repeat the exact-byte PUT and completion. Different metadata or bytes are rejected. See Asynchronous file extraction.

Rate limits

The bundled Cloudflare control plane limits each opaque API-key identity to 600 requests per 60 seconds. Successful /v1/* responses include RateLimit-Limit: 600 and RateLimit-Policy: 600;w=60. A rejected request returns 429 RATE_LIMITED plus Retry-After: 60.

Self-hosters can change the MEMORY_RATE_LIMITER binding policy in apps/web/wrangler.jsonc. The limiter hashes the bearer key before using it as the counter identity.

On this page