Handling errors and configuring retry behaviour in the Spectron SDKs.
The Spectron SDKs use a typed exception hierarchy so you can handle specific failure modes precisely. The retry policy is conservative by design: idempotent reads are retried automatically; writes are not.
Error hierarchy
All Spectron exceptions inherit from SpectronError (Python) or the SpectronError base class (JavaScript). Catching the base class covers every Spectron-originated error:
fromspectron.errorsimportSpectronError
try: ctx=awaitmemory.context(query="hello",scope={"user": "alice"}) exceptSpectronErrorase: print(e.status)# HTTP status code print(e.title)# short error type print(e.detail)# human-readable explanation print(e.extensions)# additional structured metadata, if present
Exception types
Exception
HTTP status
When it occurs
SpectronError
–
Base class; any non-2xx response not matched by a subclass
AuthError
401
Missing or invalid API key; also raised if the key has been revoked
ScopeError
403
The principal type or scope floor rejects the call – e.g. a user-scoped key attempting to access another user's data
NotFoundError
404
The requested resource (session, document, connector, etc.) does not exist
ValidationError
400 / 422
The request body is malformed, missing required fields, or fails schema validation
RateLimitError
429
The per-context rate limit or token budget has been exceeded
ServerError
5xx
An unexpected server-side error; retried automatically for idempotent requests
All exceptions carry four standard fields:
Field
Type
Description
status
int
HTTP status code
title
str
Short machine-readable error type (e.g. "not_found", "rate_limited")
detail
str
Human-readable explanation suitable for logging
extensions
dict
Additional metadata specific to the error type (e.g. retry_after for RateLimitError)
asyncdefquery_with_handling(): try: ctx=awaitmemory.context( query="what is my name?", scope={"user": "alice","org": "acme"}, ) returnctx.context
exceptAuthError: # API key is missing, expired, or revoked raiseRuntimeError("Invalid Spectron credentials – check SPECTRON_API_KEY")
exceptScopeErrorase: # The principal does not have access to the requested scope print(f"Scope denied: {e.detail}") returnNone
exceptNotFoundError: # The context or resource does not exist returnNone
exceptValidationErrorase: # Log and surface to the caller – this is a programming error raiseValueError(f"Invalid Spectron request: {e.detail}")frome
exceptRateLimitErrorase: # Back off and retry once retry_after=e.extensions.get("retry_after",5) awaitasyncio.sleep(retry_after) returnawaitmemory.context( query="what is my name?", scope={"user": "alice","org": "acme"}, )
exceptServerErrorase: # The SDK already retried 3× – escalate print(f"Spectron server error after retries: {e.detail}") returnNone
Rate limit details
RateLimitError carries a retry_after value in extensions:
exceptRateLimitErrorase: retry_after=e.extensions.get("retry_after",10)# seconds print(f"Rate limited – retry after {retry_after}s") awaitasyncio.sleep(retry_after)
}elseif(errinstanceofRateLimitError){ constretryAfter=(err.extensions?.retryAfter??10)asnumber; awaitnewPromise(resolve=>setTimeout(resolve,retryAfter*1000)); // retry once constctx=awaitmemory.context({ query:"what is my name?", scope:{user:"alice",org:"acme"}, }); returnctx.context;
}elseif(errinstanceofServerError){ console.error("Spectron server error after retries:",err.detail); returnnull;
The SDKs apply automatic retries only to idempotent requests (HTTP GET and any read-only POST such as query endpoints). Writes – turn submission, document upload, session creation – are never retried automatically.
Request type
Auto-retry
Max attempts
Backoff
Idempotent reads (GET, query POST)
Yes
3
Exponential: 250ms, 500ms, 1000ms
Writes (POST, PUT, DELETE)
No
1
–
Retries fire only on 5xx responses. 4xx errors are not retried because they indicate a client-side problem that will not resolve on its own.
Disabling auto-retry
Pass retries=0 (Python) or retries: 0 (JavaScript) to the constructor to disable all automatic retries:
Spectron enforces per-context rate limits on both requests per second and token consumption per period. For high-throughput agents, implement a simple back-off loop:
The default request timeout is 30 seconds. Streaming endpoints (when available) disable the read timeout and rely solely on the connection timeout. Adjust the timeout at the client level:
Requests that exceed the timeout raise SpectronError with status=0 and title="timeout" in Python, and a standard TypeError (network timeout) in JavaScript.