Brainby arc-labs/docs
Python SDK

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.

OptionTypeDefault / Env
statusint

The HTTP status. 0 for a transport or timeout failure (no response was received).

codestr

The stable error code from the response body (e.g. "validation"), or "transport" / "http_error" when none is available.

messagestr

A 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:

OptionTypeDefault / Env
BrainErrorbase class

Base of every client-side failure. Catch this to catch them all.

ProtocolErrorsequence violation

The peer broke the protocol sequence — an unexpected opcode, or a response on an unknown stream.

ConnectionClosedpeer closed

The peer closed the connection (a read returned zero bytes).

BrainTimeoutdeadline exceeded

An operation did not complete within its deadline. Carries timeout.

VersionMismatchhandshake failure

The server chose a wire version the client did not offer. Carries chosen and supported.

ServerErrorstructured ERROR frame

The server returned a structured error. Carries code, category, message, and retry_after_ms.

ActAsDeniedServerError subclass

The 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 failure

ServerError.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:

OptionTypeDefault / Env
0 — Protocolfatal
1 — Authenticationfatal
2 — Authorizationfatal
3 — Validationfatal
4 — NotFoundfatal
5 — Conflictfatal
6 — ResourceExhaustedretryable
7 — Internalfatal
8 — Unavailableretryable

is_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?

On this page