osyra_ome.errors
Private pre-release / network boundary: The currently usable customer surface is offline verification of an existing signed artifact against an out-of-band trust anchor. Memory/network RPC APIs and host snippets on this page describe protocol and interface shape; the public Edge bridge, package publication, and release acceptance remain pending. Do not treat
api.osyra.ai:443examples as a released customer route.
Typed error sentinels for the Osyra OME SDK.
Cross-language parity model (per ADR-045): the TypeScript sibling at ``@osyra/ome`` exposes structurally identical error classes — name-by-name parity with this module. Both SDKs raise/throw on the same conditions identified by the same OSY-MEM-NNNN / OSY-TRANS-NNNN / OSY-AUTH-NNNN error codes from the canonical proto comments.
Hierarchy:
OmeError # Root — catch-all for any SDK error ├── OmeVerifyError # Ed25519 signature verification failed ├── OmeWireFormatError # Canonical CBOR decode failed (RFC 8949 §4.2) ├── OmeBundleError # .ome ZIP bundle integrity / manifest failure ├── OmeWorkspaceError # Workspace binding / GUC / RLS violation ├── OmePolicyError # OPA / authz policy denial ├── OmeTransportError # gRPC transport / network / timeout / TLS ├── OmeServerError # Server-side INTERNAL / UNAVAILABLE ├── OmeAuthError # Token expired / invalid / missing ├── OmeRateLimitError # Rate limit / tier-quota exceeded ├── OmeNotFoundError # Resource not found in caller's workspace └── OmeBodyUnavailableError # Claim found, but body bytes not on this read path
Discrimination pattern (mirrors Go's ``errors.Is`` + TS's instanceof):
try:
client.verify.receipt(bytes_)
except OmeVerifyError as e:
# e.code == "OSY-MEM-5101" (verbatim from server response)
# str(e) == "[OSY-MEM-5101] Ed25519 signature verification failed"
...
except OmeError:
# any other SDK error
...Cross-process serialization: every sentinel is a plain Exception subclass that supports ``copy.deepcopy()`` and the standard library's ``pickle`` module round-trip. This is verified by ``tests/test_errors.py`` to keep multiprocessing-safety contracts intact.
ADR-044 stability commitment: error class names + their inheritance relationship are part of the public API surface from v1.0.0 onward. New sub-classes may be added (semver-MINOR), but existing names will not be renamed without a deprecation cycle.
Classes
class OmeAuthError
Bases: OmeError
Token expired / invalid / missing.
Raised when the bearer token attached to the gRPC metadata is rejected by the Edge Gateway (JWT signature invalid, exp claim in the past, missing required scope, etc.).
Server codes: ``OSY-AUTH-1001..1099`` (per osyra-response-common error-code registry). Local code: ``OSY-SDK-1000``.
Note: this is auth-N (identity), NOT auth-Z (policy). For policy denials see :class:`OmePolicyError`.
class OmeBodyUnavailableError
Bases: OmeError
A claim was found, but its body bytes are not available on this read path.
Raised when a caller (typically a body-bearing agent-framework adapter such as the LangGraph checkpoint saver or the AutoGen memory store) resolves a *known* ``claim_id`` to a :class:`~osyra_ome.types.Claim` whose ``body`` is empty (``b""``).
ADAPT2-1 (ENG-2225): the v0.1 read surface (``client.memory.get_claim``, wired over ``ListClaims``) returns a sanitized *projection* that NEVER carries the opaque claim body — ``body=b""`` on every read (see :meth:`osyra_ome.OmeClient.MemoryNamespace.get_claim`). A body-bearing adapter that reconstructs application state from the body therefore has NOTHING to reconstruct from. Returning ``None`` / an empty list in that case is a SILENT data-loss: an agent resuming a thread would behave as though the thread were brand-new, discarding every checkpoint it had written. This SDK fails CLOSED instead — it raises so the caller can diagnose the gap rather than silently lose memory.
Distinct from :class:`OmeNotFoundError` (the claim does not resolve at all) — here the claim *exists* and its metadata verified; only the body transport is missing. Body-bearing read-back is deferred to v0.2 via a dedicated ``GetClaimBody`` gRPC RPC (NOT the aspirational REST path that earlier docstrings referenced and that the server does not implement).
Local code: ``OSY-SDK-5302``.
class OmeBundleError
Bases: OmeError
`.ome` ZIP bundle integrity or manifest failure.
Raised by:
- ``client.verify.bundle_manifest(path)`` — manifest decode/verify failed
- ``client.memory.export_bundle/import_bundle(...)`` — server bundle RPCs
Server codes: ``OSY-MEM-5251..5254``. Local code: ``OSY-SDK-5250``.
class OmeCBORCanonicalError
Bases: OmeWireFormatError
Canonical-CBOR strictness violation (RFC 8949 §4.2.1 / §5.6).
Raised when decoded bytes violate canonical/deterministic form — duplicate map keys (§5.6) or indefinite-length items (non-canonical). Per threat-model **BC-15** and ADR-045 cross-language parity (the Go reference rejects these via ``DupMapKeyEnforcedAPF`` + ``IndefLengthForbidden``). Subclass of :class:`OmeWireFormatError` so existing ``except OmeWireFormatError`` callers still catch it.
Local code: ``OSY-SDK-5104``.
class OmeCBORChunkLimitError
Bases: OmeWireFormatError
CBOR input exceeded a size / chunk limit (BC-15 / A3).
Raised when an envelope exceeds the configured byte cap (A3 1 MiB receipt cap) or an indefinite-length primitive floods chunks. Closes the memory-exhaustion DoS surface on the verify path.
Local code: ``OSY-SDK-5106``.
class OmeCBORDepthError
Bases: OmeWireFormatError
CBOR nesting exceeded the maximum decode depth (BC-15 recursion cap).
Prevents stack-exhaustion (crash-on-read) DoS from deeply-nested input. Raised by the verify-side decoder before the hand walker or ``cbor2`` can recurse past ``max_depth``.
Local code: ``OSY-SDK-5105``.
class OmeError
Bases: Exception
Root error type for the Osyra OME SDK.
Catch this to handle any SDK-originated error generically. Subclasses carry the same constructor signature, so callers can inspect ``.code`` + ``.message`` on every raised exception.
Attributes:
message: Human-readable description of the failure.
code: Stable OSY-*-NNNN error code from the server, or one of
the SDK-internal codes (OSY-SDK-NNNN) for client-side
failures (e.g. CBOR decode that never reached the wire).
None only when raised speculatively from a non-coded
context (rare; treat as best-effort).
cause: Optional underlying exception (set by SDK internals
via raise ... from exc; accessible via __cause__
too for compatibility with PEP 3134).
Methods
__init__
def __init__(self, message: str, *, code: str | None = None, cause: BaseException | None = None) -> Noneclass OmeNotFoundError
Bases: OmeError
Resource not found in caller's workspace.
Raised when:
- ``client.memory.get_claim(id)`` — claim_id doesn't resolve OR the RLS-filtered read returned empty (workspace-existence is NEVER leaked across tenants)
- any ``ProveTombstoned`` / ``GetReceipt`` resolved to empty
Server codes: ``OSY-MEM-5181..5183``, ``5301``, ``5129``. Local code: ``OSY-SDK-5301``.
Security: this exception NEVER discriminates "doesn't exist" from "exists but in another workspace" — both surface the same code and message. Leaking that distinction would create a cross-tenant enumeration oracle (ADR-040 / ENG-1215 anti-enumeration policy).
class OmePolicyError
Bases: OmeError
OPA / authz policy denial.
Raised when the server's OPA policy gate denied the operation (e.g. ``RevokeSignerPub`` requires ``owner`` or ``security-admin`` role + recent MFA challenge). NOT the same as ``OmeAuthError`` (which is about the token itself) or ``OmeNotFoundError`` (which masks workspace-existence on RLS-filtered reads).
Server codes: ``OSY-MEM-5127..5128``. Local code: ``OSY-SDK-5127``.
class OmeRateLimitError
Bases: OmeError
Rate limit or tier-quota exceeded.
Raised when the workspace's tier (FREE/PRO/ENTERPRISE) quota is exhausted (e.g. monthly claim-write count) OR when a per-RPC rate limit was hit (e.g. ``RevokeSignerPub`` 10 calls/hour).
Server codes: ``OSY-RATE-2001..2099``, ``OSY-MEM-5137``. Local code: ``OSY-SDK-2000``.
Callers MAY retry with exponential backoff using ``Retry-After`` metadata (v0.2 ships a helper for this).
class OmeServerError
Bases: OmeError
Server-side ``INTERNAL`` or ``UNAVAILABLE`` failure.
Raised when the gRPC trailer reports a Status the SDK classifies as "the server is misbehaving" (``INTERNAL``, ``UNAVAILABLE``, ``UNKNOWN``). Distinct from :class:`OmeTransportError` (network / TLS / deadline) and :class:`OmePolicyError` / :class:`OmeAuthError` (semantic refusals with a stable OSY-* code).
Server codes: usually empty; the gRPC Status alone is the signal. Local code: ``OSY-SDK-9100``.
Callers SHOULD log the underlying ``rpc_err.details()`` and surface to operators rather than auto-retrying — retrying a server-internal bug often just doubles the log volume without changing the outcome.
class OmeTransportError
Bases: OmeError
gRPC transport / network / timeout / TLS failure.
Raised when the gRPC channel cannot reach the server, the TLS handshake fails, the deadline expired, or the server returned a Status outside the application-coded range. Distinct from :class:`OmeServerError` which is raised on ``INTERNAL``/``UNAVAILABLE`` server-side failures that come back with a Status trailer.
The split exists so callers can write resilient retry loops:
- ``OmeTransportError`` (network) → retry with backoff is usually safe.
- ``OmeServerError`` (server bug) → retry might mask the symptom; prefer reporting + escalation.
Distinct from ``client_closed`` raised by methods called after ``OmeClient.close()`` — that's a ``RuntimeError`` (client lifecycle bug, not transport).
Local code: ``OSY-SDK-9000``.
class OmeVerifyError
Bases: OmeError
Ed25519 signature verification failed.
Raised by:
- ``client.verify.receipt(bytes)`` — local Ed25519 check failed
- ``client.memory.write_claim(...)`` — server returned 5101
- ``client.verify.proof/witness/bundle_manifest(...)`` — local checks
Server codes: ``OSY-MEM-5101..5103``. Local code: ``OSY-SDK-5101``.
Security: do NOT downgrade this to a string-typed error — verify-side callers MUST be able to discriminate "the body decoded but signature failed" (this exception) from "transport error before verify ran" (``OmeTransportError``). Conflating them is a textbook fail-open vulnerability.
class OmeWireFormatError
Bases: OmeError
Request/wire-format error — the bytes or request are malformed.
Raised when bytes presented to the verify-side mini-kernel are not well-formed canonical CBOR, OR when they decode but violate the OAP-MEM v0.1 schema. Also the typed error for a server-rejected request shape — gRPC ``INVALID_ARGUMENT`` / ``OUT_OF_RANGE`` map here (the request is invalid; retrying it unchanged will never succeed), distinct from a transport fault. Distinct from ``OmeVerifyError`` — this is structural; that is cryptographic.
Server codes: ``OSY-MEM-5102``. Local code: ``OSY-SDK-5102``.
class OmeWorkspaceError
Bases: OmeError
Workspace binding / GUC / RLS violation.
Raised when the server rejects a request because the caller's workspace_id doesn't match the resource's owning workspace, or when the Postgres GUC ``ome.workspace_id`` could not be bound (server bug, but surfaces to the client).
Server codes: ``OSY-MEM-5310..5312``. Distinct from ``OmeAuthError`` (which is about identity, not tenancy).