Resources
Errors
How Telem reports failures: typed SDK exceptions, the HTTP status for each, and how the agent plugins and the MCP server show a failed call.
Use this page to find out what a failed Telem call means. Every non-2xx response from Search or Fetch maps to one of a few typed exceptions. This is the same for every client.
Status codes and exceptions
Section titled “Status codes and exceptions”In the Python SDK, raise_for_status() does the mapping. Every exception
derives from TelemError and has .message, .status_code and .body:
| HTTP status | Exception | Meaning |
|---|---|---|
400 |
BadRequestError |
Malformed request. Example: an unknown provider name |
401 |
AuthError |
Missing or invalid API key |
402 |
APIStatusError |
The account cannot pay for the call: the billing subscription is suspended, or the prepaid credit is used up. The message says which. Fetch and monitors give the code payment_required |
403 |
AuthError |
The key is valid but is not allowed to make this call |
403, body not JSON |
APIStatusError |
A firewall blocked the request before it reached Telem. The key is not the problem. The request text can have characters that are not allowed |
404 |
NotFoundError |
The resource (e.g. a session id) doesn’t exist |
405 |
APIStatusError |
The endpoint does not take this HTTP method. Example: GET /v1/fetch. Fetch and monitors give the code method_not_allowed |
409 |
APIStatusError |
missing_snapshots: the request leaves out earlier conversation context that Telem does not have. Nothing ran; send it again with that context |
422 |
APIStatusError |
The body failed validation. Example: an auto_routing value other than accuracy |
429 |
APIStatusError |
A per-minute limit: the account’s (by default 6,000 search queries or fetched URLs a minute), or the key’s, if one was set. The message says which. Wait for the seconds in Retry-After, then try again |
502 |
APIStatusError |
Fetch only. provider_unavailable: you pinned providers and every URL failed before its page was reached |
503 |
APIStatusError |
Search: all_providers_failed, every provider call failed (Retry-After: 1 when a retry can help). With a plain-string message: Telem turned the request away before it ran; try again later |
504 |
APIStatusError |
deadline_exceeded: too little time was left to start any provider call. Safe to retry with backoff |
| any other non-2xx | APIStatusError |
Everything else, including 500 |
For the limits behind a 429, see Rate limits. For what a
call costs, see Pricing.
The SDK takes its error message from the error body. The
message is error.message, or the detail string. For validation errors, it is
each item’s msg, joined with ", ". When detail is an object, the message
is only Unexpected status code N. Read the code from
exc.body["detail"]["code"].
Two failures have no status code, because no HTTP response arrived:
| Exception | Raised when |
|---|---|
TelemConnectionError |
The request timed out or the transport failed before any response arrived |
TelemTimeoutError |
A TelemConnectionError for a timeout. Telem can have received the request. After a monitor create, list your monitors before you try again |
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)The status codes in the first table apply to every Telem surface. The MCP server, the agent-tool plugins and any client that calls the HTTP API directly all get the same status codes for the same reasons.
The hosted MCP server also checks every request before any tool runs. When the first request fails, your MCP client cannot connect:
401: the API key is missing or not valid, or the server could not check it.400: anX-Telem-*header has a value the server does not accept.413: the request body is over 1,000,000 bytes.503: the MCP server is not turned on for this deployment.
Error bodies
Section titled “Error bodies”A Search error has a detail field. It is a string, a list of validation
errors, or an object with a code. You get the object for 409, 503 and
504:
{"detail": {"code": "all_providers_failed", "reason": "provider_errors"}}Fetch and monitors answer with an error object:
{"error": {"code": "invalid_request", "message": "...", "param": "urls[1]"}}Check code in your code, because the message text can change. When param
is present, it names the field that is not correct.
Only fetch (/v1/fetch) and monitors (/v1/monitors) use the error object.
Search (/v1/search and /v1/interactions) and every other route keep the older
detail shape. This includes a route under /v1/ that does not exist, which gives
404 with {"detail": "Not Found"}. Telem keeps the older shape on these routes
so that existing clients do not break. The Python and JavaScript SDKs read both
shapes. If you call the HTTP API directly, check for both error and detail.
How the agent-tool plugins handle errors
Section titled “How the agent-tool plugins handle errors”OpenClaw, OpenCode, Pi and DeepSeek Harness each build telem_search and
telem_fetch on the same two endpoints. All four handle a failure in the same
way. There are two cases.
A partial failure shows inline. It shows next to the results that came
back. If one provider in a search fails and others succeed, the interaction
still succeeds.
The same is true for one URL in a telem_fetch batch. The failure shows as a
line in the formatted tool result:
- Search:
[provider] failed: <message> - Fetch: a
### <url>section withError: <type>: <message>in place of the page content
The hosted MCP server, which Claude Code, Codex and other MCP clients use, shows a
failed search provider with the same [provider] failed: <message> line. A provider
whose results could not be read gets [provider] no rows (<reason>).
A request-level failure throws. When the POST itself returns a non-2xx
status, the tool’s execute() throws a JavaScript Error. It returns no
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 or turn it into result text. That is the
host’s job. OpenClaw’s saved transcript has an isError flag on tool results.
The plugin reads this flag back when it rebuilds the conversation history. This
flag is the standard way for a host to tell the model that a tool call failed
without stopping the conversation.
The Hermes plugin shows a failed provider or URL in the same way. A request-level
failure comes back as a Python SDK error instead, with the server’s message, such as
Invalid API key.
Claude Code, Codex and other MCP clients use the hosted MCP server, which works
differently. It shows no line for a failed provider: the results of the providers
that succeeded come back alone, and when every provider fails, the model sees
No results found. When the request itself fails, the tool returns error text, for
example The Telem router rejected the request (HTTP <status>) for an HTTP error.
Next steps
Section titled “Next steps”- API keys: fix a missing or invalid API key
- Rate limits: the limits behind a
429 - Search parameters: the options that a search accepts
- Fetch parameters: the options that a fetch accepts