Errors
The exception hierarchy for both clients — BrainHttpError (HTTP) and the BrainError family (wire), plus is_retryable.
HTTP: BrainHttpError
BrainHttpClient raises exactly one exception type, BrainHttpError, for
every failure. It mirrors the Rust and TypeScript BrainHttpError.
statusintThe HTTP status. 0 for a transport or timeout failure (no response was
received).
codestrThe stable error code from the response body (e.g. "validation"), or
"transport" / "http_error" when none is available.
messagestrA human-readable message.
from brain_db_sdk import BrainHttpClient
from brain_db_sdk.http import BrainHttpError
client = BrainHttpClient("sk-...", base_url="https://api.arc-labs.ai")
try:
client.recall("...")
except BrainHttpError as err:
if err.status == 0:
... # transport / timeout — safe to retry
elif err.status == 401:
... # auth rejected — fix the key
else:
print(err.status, err.code, err.message)Only 503 and transport/timeout failures (status == 0) are retryable; every
4xx is a terminal client verdict. See Retries.
Wire: the BrainError hierarchy
BrainClient raises subclasses of BrainError, one per failure layer:
BrainErrorbase classBase of every client-side failure. Catch this to catch them all.
ProtocolErrorsequence violationThe peer broke the protocol sequence — an unexpected opcode, or a response on an unknown stream.
ConnectionClosedpeer closedThe peer closed the connection (a read returned zero bytes).
BrainTimeoutdeadline exceededAn operation did not complete within its deadline. Carries timeout.
VersionMismatchhandshake failureThe server chose a wire version the client did not offer. Carries chosen
and supported.
ServerErrorstructured ERROR frameThe server returned a structured error. Carries code, category,
message, and retry_after_ms.
ActAsDeniedServerError subclassThe connection principal is not entitled to run the op under the requested
act_as identity (wire code 0x0033).
from brain_db_sdk import (
BrainClient, Auth, RecallBuilder,
BrainError, ServerError, ActAsDenied, BrainTimeout, is_retryable,
)
with BrainClient.connect("127.0.0.1", 9090, Auth.token(b"my-token")) as client:
try:
client.recall(RecallBuilder("...").build())
except ActAsDenied:
... # lacks can_act_as, or namespace outside the allowlist
except ServerError as err:
print(f"{err.code:#06x}", err.category, err.retry_after_ms)
except BrainTimeout:
... # bump request_timeout, or retry
except BrainError:
... # any other client-side failureServerError.from_response(...) builds the most specific subclass for a wire
code (e.g. ActAsDenied); unmapped codes surface as the base ServerError.
ServerError categories
ServerError.category is the coarse class of the ERROR frame:
0 — Protocolfatal1 — Authenticationfatal2 — Authorizationfatal3 — Validationfatal4 — NotFoundfatal5 — Conflictfatal6 — ResourceExhaustedretryable7 — Internalfatal8 — Unavailableretryableis_retryable
is_retryable(exc) reports whether retrying could plausibly succeed. A
transport drop or timeout (ConnectionClosed, BrainTimeout, OSError), or a
ResourceExhausted / Unavailable server verdict, is retryable; a
malformed-input or auth verdict is not.
from brain_db_sdk import is_retryable, with_retry
# with_retry uses is_retryable internally; see the Retries page.
answer = with_retry(lambda: client.recall(req))Frame-codec failures raise FrameError (from brain_db_sdk.wire.frame) — a
corrupt frame is fatal for the connection — and CBOR failures raise from
cbor2. These are outside the BrainError hierarchy.
Was this page helpful?