Errors
The SDK raises typed exceptions for every failure mode. All exceptions
live in openapp_sdk.errors and inherit from SdkError.
Hierarchy
Section titled “Hierarchy”SdkError├── ApiError # backend returned a structured error envelope├── HttpError # backend returned a non-OK response w/o a JSON envelope├── AuthError # 401/403, invalid token format, missing credentials├── TransportError # network failure, timeout, DNS, TLS├── ValidationError # backend 400/422 with field-level errors├── ConfigError # client misconfiguration (bad base URL, unusable key)└── SerializationError # response body could not be decodedBoth sync and async clients raise the same exception types.
Handling specific errors
Section titled “Handling specific errors”from openapp_sdk.errors import ( ApiError, AuthError, TransportError, ValidationError,)
try: client.orgs.create(name="")except ValidationError as err: # err.fields is a dict[str, list[str]] of field → messages. for field, messages in err.fields.items(): print(f"{field}: {', '.join(messages)}")except AuthError: print("API key expired — rotate it.")except ApiError as err: print(f"[{err.status}] {err.code}: {err.message}")except TransportError: print("Network issue — will retry.")Attributes
Section titled “Attributes”| Field | Available on | Description |
|---|---|---|
status | ApiError, HttpError, AuthError, ValidationError | HTTP status code. |
code | ApiError, ValidationError | Backend-defined error code (e.g. ORG_NAME_REQUIRED). |
message | All | Human-readable message. |
request_id | All that wrap an HTTP response | Backend request ID, forwarded from the X-Request-Id response header. Quote this when reporting bugs. |
fields | ValidationError | Field-level validation messages. |
cause | All | The underlying exception (e.g. httpx.ReadTimeout), if any. |
Retries
Section titled “Retries”The SDK retries transient failures (HTTP 5xx, connection errors, timeouts)
automatically. Errors you see are final — you don’t need your own retry loop
for the common cases. Tune how many attempts the core transport may take with
Client.connect(..., max_retries=...); see the Python SDK overview
and Errors & retries.
Request ID propagation
Section titled “Request ID propagation”Every response carries an X-Request-Id header; the SDK attaches it to the
raised exception and emits it in log records. When you file a support ticket,
include the request ID — backend logs are keyed on it.
try: client.devices.get("dev_missing")except ApiError as err: log.error("Device lookup failed", extra={"openapp_request_id": err.request_id}) raisePitfalls
Section titled “Pitfalls”- Catching
Exception: don’t. Always catchSdkErroror a specific subclass so the runtime halts on genuinely unexpected errors. - Comparing
err.codestrings: the backend defines the set of codes; treat unknown codes as soft failures rather than asserting a closed set. - Mutating
err.fields: it’s a snapshot of the server’s response; treat it as read-only.