Errors
Both SDKs ship the same exception hierarchy, with every class descending from
TelerException. Some are raised by client-side validation (for example, an
empty API key or an unsupported stream type); others are mapped from HTTP
error responses. The two SDKs do not map every non-2xx status to a typed
exception, so read the mapping table below carefully.
Hierarchy
Section titled “Hierarchy”| Exception | code | When raised |
|---|---|---|
BadParametersException | 400 | Missing or invalid parameter. Carries .param. |
UnauthorizedException | 401 | API key invalid, expired, or revoked. |
ForbiddenException | 403 | Authenticated but not allowed. |
NotImplementedException | 501 | Feature unsupported (e.g. unidirectional streams). |
TelerException | 500 | Base class. Extend or use as a broad catch. |
How HTTP errors map
Section titled “How HTTP errors map”The SDKs differ in which HTTP statuses become typed exceptions:
| Source | Node | Python |
|---|---|---|
| HTTP 401 | UnauthorizedException | not converted |
| HTTP 403 | ForbiddenException | ForbiddenException |
| any other non-2xx | TelerException (.code = HTTP status) | not converted |
| empty API key | BadParametersException | BadParametersException |
empty/unparseable remote_url | BadParametersException | BadParametersException |
| unidirectional stream | NotImplementedException | NotImplementedException |
| bad stream-handler return | TelerException | BadParametersException |
So BadParametersException and NotImplementedException are raised
client-side, not returned by the server. The Node client wraps any non-401/403
HTTP error as a generic TelerException whose .code is the HTTP status; the
Python client only auto-maps 403.
Python catch pattern
Section titled “Python catch pattern”Exception classes live in teler.exceptions and are not re-exported from
the top-level teler package, so import them from teler.exceptions. Use the
broad TelerException as your last except clause to avoid leaking SDK
internals.
from teler import Clientfrom teler.exceptions import ( BadParametersException, ForbiddenException, TelerException,)
with Client("YOUR_API_KEY") as client: try: call = client.calls.create( from_number="+918065xxxx", to_number="+919967xxxx", flow_url="https://your-domain.com/flow", status_callback_url="https://your-domain.com/webhook", ) except BadParametersException as e: log.warning("Invalid %s: %s", e.param, e) except ForbiddenException: log.error("from_number not on this account") raise except TelerException as e: log.exception("Teler error: %s", e) raiseNode catch pattern
Section titled “Node catch pattern”All Teler exceptions extend Error, so a generic catch (err) block sees
them; use instanceof to discriminate. Each instance exposes message,
code, and name.
import { Client, BadParametersException, UnauthorizedException, ForbiddenException, TelerException,} from "@frejun/teler";
const client = new Client("YOUR_API_KEY");
try { const call = await client.calls.create({ from_number: "+918065xxxx", to_number: "+919967xxxx", flow_url: "https://your-domain.com/flow", status_callback_url: "https://your-domain.com/webhook", });} catch (err) { if (err instanceof BadParametersException) { console.warn(`Invalid ${err.param}: ${err.message}`); } else if (err instanceof UnauthorizedException) { console.error("API key invalid"); throw err; } else if (err instanceof ForbiddenException) { console.error("from_number not on this account"); throw err; } else if (err instanceof TelerException) { console.error(`Teler error: ${err.message}`); throw err; } else { throw err; }}Custom error messages
Section titled “Custom error messages”Every subclass accepts an optional message string. Use it when raising your own validation errors that should travel through the same channel.
from teler.exceptions import BadParametersException
raise BadParametersException( param="from_number", msg="from_number must be in E.164 format",)import { BadParametersException } from "@frejun/teler";
throw new BadParametersException( "from_number", "from_number must be in E.164 format",);Retry strategy
Section titled “Retry strategy”UnauthorizedException, ForbiddenException, and BadParametersException
indicate caller errors: don’t retry. Fix the input.
TelerException (5xx) and transport-level failures are usually transient.
Retry with exponential backoff and jitter, then circuit-break.
| Attempt | Delay |
|---|---|
| 1 | immediate |
| 2 | 1s + jitter |
| 3 | 2s + jitter |
| 4 | 4s + jitter |
Stop after 3-5 attempts. Use a circuit breaker for sustained degradation.