SurrealDB Agent Memory uses standard HTTP status codes and follows RFC 7807 Problem Details for all error responses.
Spectron was the project name for SurrealDB Agent Memory. These type names
will be renamed in a future release.
Error response format
All errors return a JSON body with the following fields:
{
"type": "https://spectron.dev/errors/context-not-found",
"title": "Context not found",
"status": 404,
"detail": "No context with id 'acme-staging' exists on this server.",
"instance": "/api/v1/contexts/acme-staging"
}| Field | Description |
|---|---|
type | A URI identifying the error type. Stable across versions. |
title | A short, human-readable summary of the problem type. |
status | The HTTP status code. |
detail | A human-readable explanation specific to this occurrence. |
instance | The request path that produced the error. |
HTTP status codes
400 Bad Request
The request body or query parameters are invalid. Common causes:
Malformed JSON body
Missing required fields
Invalid field values (e.g. unknown
modefor knowledge query)Scope floor violation (requesting a scope narrower than the key's floor)
{
"type": "https://spectron.dev/errors/validation-error",
"title": "Validation error",
"status": 400,
"detail": "Field 'mode' must be one of: vector, bm25, hybrid, hybrid_graph. Got: 'fuzzy'.",
"instance": "/api/v1/acme-prod/query"
}401 Unauthorized
No Authorization: Bearer token was provided, or the key is malformed.
{
"type": "https://spectron.dev/errors/unauthorized",
"title": "Unauthorized",
"status": 401,
"detail": "API key missing. Include 'Authorization: Bearer <key>' in your request.",
"instance": "/api/v1/acme-prod/sessions"
}403 Forbidden
The API key is valid but does not have permission to perform this operation. Common causes:
Agent key attempting a management operation
The requested scope falls outside the key's granted region for the verb
Agent key attempting to persist a reflection (requires supervisor principal)
{
"type": "https://spectron.dev/errors/forbidden",
"title": "Forbidden",
"status": 403,
"detail": "This operation requires a management key. The provided key has principal 'agent'.",
"instance": "/api/v1/contexts"
}404 Not Found
The requested resource does not exist.
{
"type": "https://spectron.dev/errors/not-found",
"title": "Not found",
"status": 404,
"detail": "No document with id 'document:0197d8f2...' exists in context 'acme-prod'.",
"instance": "/api/v1/acme-prod/documents/0197d8f2"
}409 Conflict
A resource with the same identifier already exists, or an idempotency conflict occurred:
Duplicate Context id on create
Duplicate principal
display_nameon create (when no matchingexternal_idcreate-or-get applies)Same
Idempotency-Keywith a different request body on/factsor/facts/batchDuplicate idempotency request while the first is still in flight
{
"type": "https://spectron.dev/errors/conflict",
"title": "Conflict",
"status": 409,
"detail": "A context with id 'acme-prod' already exists.",
"instance": "/api/v1/contexts/acme-prod"
}413 Payload Too Large
The uploaded file exceeds the per-Context size limit.
{
"type": "https://spectron.dev/errors/payload-too-large",
"title": "Payload too large",
"status": 413,
"detail": "Uploaded file size (52.4 MB) exceeds the per-context limit (50 MB).",
"instance": "/api/v1/acme-prod/documents"
}422 Unprocessable Entity
The request is syntactically valid but semantically invalid.
{
"type": "https://spectron.dev/errors/unprocessable",
"title": "Unprocessable entity",
"status": 422,
"detail": "Cannot bind context to namespace 'spectron' - this namespace is reserved for internal use.",
"instance": "/api/v1/contexts/test"
}429 Too Many Requests
The Context is blocked from LLM-backed work, or a per-minute rate limit was hit.
Token budget: returns 429 when enforcement_blocked is true on the Context (org credit enforcement on Cloud, or an operator-set block). A soft token_limit breach alone does not reject while enforcement_blocked is false - usage continues under pay-as-you-go.
Applies to LLM-backed paths including /chat, /facts?infer=full, /reflect, and /consolidate - not to read-only cache hits or direct lookups.
{
"type": "https://spectron.dev/errors/rate-limited",
"title": "Too many requests",
"status": 429,
"detail": "Token enforcement is blocked for context 'acme-prod'.",
"instance": "/api/v1/acme-prod/sessions/sess_abc/turns",
"retry_after": null
}500 Internal Server Error
An unexpected error occurred server-side. The detail field contains a request ID for support escalation.
{
"type": "https://spectron.dev/errors/internal",
"title": "Internal server error",
"status": 500,
"detail": "An unexpected error occurred. Request ID: req_01HF3X...",
"instance": "/api/v1/acme-prod/context"
}503 Service Unavailable
The server is temporarily unable to handle requests - typically during a SurrealDB connection issue or startup.
SDK exceptions
Python SDK
| Exception | HTTP status | When |
|---|---|---|
SpectronAuthError | 401 | Missing or invalid API key |
SpectronScopeError | 403 | Scope floor or principal rejects the call |
SpectronNotFoundError | 404 | Resource does not exist |
SpectronAPIError | Other non-2xx | Generic API failure (includes 400, 409, 429, 5xx) |
from surrealdb import SpectronNotFoundError, SpectronAPIError
try:
doc = await client.documents.get("document:nonexistent")
except SpectronNotFoundError as e:
print(f"Document not found: {e.message}")
except SpectronAPIError as e:
if e.status_code == 429:
print(f"Rate limit exceeded: {e.body}")See the SDK error sections for Python and JavaScript for the full hierarchy and retry behaviour.
JavaScript SDK
| Error class | HTTP status | When |
|---|---|---|
AuthError | 401 | Missing or invalid API key |
ScopeError | 403 | Scope floor or principal rejection |
NotFoundError | 404 | Resource does not exist |
ValidationError | 400, 422 | Invalid request payload |
RateLimitError | 429 | Token or rate limit exceeded |
ServerError | 500, 503 | Server-side failure |
ConnectionError | - | Network failure or timeout |
import { NotFoundError, RateLimitError } from "@surrealdb/spectron";
try {
const doc = await client.documents.get("document:nonexistent");
} catch (e) {
if (e instanceof NotFoundError) {
console.error("Document not found:", e.detail);
} else if (e instanceof RateLimitError) {
console.error("Rate limit exceeded");
}
}Ingestion pipeline errors
Documents that fail during async processing do not return HTTP errors - they set the document status to "failed" and populate the error field:
{
"id": "document:0197d8f2...",
"status": "failed",
"error": "PDF extraction failed: file is encrypted and no password was provided.",
"processing_started_at": "2026-05-12T14:22:11Z",
"processing_completed_at": "2026-05-12T14:22:14Z"
}Poll GET /api/v1/{context_id}/documents/{id} to check document status. See Uploading documents for retry guidance.
MCP error handling
MCP tool failures use a different envelope from REST, but carry the same HTTP status semantics:
Operation failures →
isError: truetool result withstructuredContent.error.status(404, 403, 429, etc.). The JSON-RPC transport returns HTTP 200.Protocol faults → JSON-RPC
error(bad params, unknown tool).
Auth failures and missing Contexts are masked as 401, never 404, so unauthenticated callers cannot enumerate Context ids. See MCP tools.