Skip to content

Errors

Every non-2xx response from Search or Fetch maps to one of a small set of typed exceptions, whichever client makes the call.

The Python SDK’s raise_for_status() does the mapping; every exception derives from TelemError and carries .message, .status_code, and .body:

HTTP status Exception Meaning
400 BadRequestError Malformed request — e.g. an unknown provider name
401 / 403 AuthError Missing or invalid credentials
402 APIStatusError Monthly spend limit would be exceeded — a spend cap the account set for itself; raise or remove it
404 NotFoundError The resource (e.g. a session id) doesn’t exist
429 APIStatusError Rate limited — per-key requests/minute (Retry-After: 60) or the account’s daily quota (Retry-After: 3600); back off for the header’s seconds
any other non-2xx APIStatusError Everything else, including 5xx

The 402/429 ceilings are opt-in guardrails, not built-in limits: each exists only if set on your key, project, or account — unset means no ceiling, and having credit means you keep going. Need more? Tell us.

The error message includes the response body’s detail field when present — a plain string, or, for FastAPI validation errors, each item’s msg joined with ", ".

Two failures never reach a status code at all, because no HTTP response was received to map:

Exception Raised when
TelemConnectionError The request timed out or the transport failed before any response arrived
TelemServerVersionError The router answered without the normalized response the SDK requires (normalized_schema_version < 2)
from telem import Telem, BadRequestError
try:
Telem().search("hi", providers_include=["does-not-exist"])
except BadRequestError as exc:
print(exc.status_code, exc.message)

This table is the ground truth for every Telem surface, not just the SDK: the MCP server, the agent-tool plugins, and any client calling the HTTP API directly all see the same status codes for the same reasons.

OpenClaw, OpenCode, and Pi each wire up telem_search and telem_fetch on top of the same two endpoints, and all three handle failure the same way, in two cases.

A partial failure renders inline, next to the results that did come back. When one provider in a search (or one URL in a telem_fetch batch) fails while others succeed, the interaction still succeeds and the failure shows up as a line inside the formatted tool result:

  • Search: [provider] failed: <message>
  • Fetch: ### <url> section with Error: <type>: <message> instead of page content

A request-level failure throws. When the POST itself returns non-2xx, the tool’s execute() throws a JavaScript Error rather than returning formatted text:

Telem search failed: HTTP 401 <first 200 characters of the response body>
Telem fetch failed: HTTP 401 <first 200 characters of the response body>

The plugin does not catch that throw and turn it into result text — that is the host’s job. OpenClaw’s persisted transcript carries an isError flag on tool results, which the plugin reads back when it rebuilds conversation history: the standard way a host tells the model a tool call failed without stopping the conversation.