Errors and status codes
HTTP status codes, error response shape, and automatic retry behavior for failed document processing.
The RAG API uses standard HTTP status codes. All error responses share a consistent JSON body.
Error response shape
{
"message": "Human-readable error description",
"cause": {}
}| Field | Type | Description |
|---|---|---|
message | string | Description of the error. Always present. |
cause | any | The underlying error object. Present on server errors; may be empty on client errors. |
Status codes
| Code | Meaning | Common causes |
|---|---|---|
200 OK | Request succeeded. | — |
201 Created | Resource created. | Returned by POST /documents/embed/text and POST /documents/embed/pdf. |
400 Bad Request | Invalid request body or parameters. | Missing required fields, invalid agentId, wrong file type, or rollback called without both path params. |
401 Unauthorized | Authentication failed. | Missing Authorization header, invalid or expired token, internal API key does not match NESTJS_API_KEY. |
403 Forbidden | Authenticated but not permitted. | Agent does not own the document or chunk being modified. |
404 Not Found | Resource does not exist. | Unknown chunkId, no edit history on the chunk, or the requested version ID is absent from history. |
413 Payload Too Large | File exceeds the size limit. | PDF file is larger than 10 MB. |
422 Unprocessable Entity | Request is structurally valid but cannot be processed. | Rollback target version has no previous_content to restore. |
500 Internal Server Error | Unexpected server error. | Supabase query failure, embedding service unavailable, or unhandled exception. |
Retrying failed document processing
Documents and source texts pass through a processing pipeline after ingestion. If processing fails, the document's status field is set to failed. The API does not surface this status directly in the ingestion response — polling or webhooks are needed to observe it.
Automatic retry behavior
The DocumentsRetryService runs a background sweep every 5 minutes. It automatically resets eligible failed documents back to new status so the processing queue re-picks them up. A document is eligible for retry if:
- Its
statusisfailed. - Its
retry_countis below the configured maximum (default: 3 attempts, configurable viaDOCUMENT_MAX_RETRIES). - It has been in the
failedstate for at least 10 minutes since the last failure (configurable viaDOCUMENT_RETRY_BACKOFF_MS).
Documents that exhaust all retry attempts remain in the failed state permanently. Their last_error field is preserved for debugging.
Document lifecycle states
| Status | Meaning |
|---|---|
new | Ingested and waiting to be picked up by the processing queue. |
queued | Added to the BullMQ processing queue. |
processing | Actively being chunked and embedded. |
completed | Processing finished; chunks are available for search. |
failed | Processing encountered an unrecoverable error. Eligible for automatic retry if within retry budget. |
Authentication errors in detail
The ApiAuthGuard returns 401 Unauthorized for any of the following:
- The
Authorizationheader is missing entirely. - A
Bearer nest-*token does not match the server'sNESTJS_API_KEY. - A guest JWT (
Bearer JWT Guest …orBearer JWT Public Guest …) fails signature verification. - A Supabase user JWT is invalid or expired.
When a 401 is returned, the message field contains one of:
"Missing authorization header""Invalid internal API key""Invalid guest token format"