tex.TexError. Most apps catch one of these:
| Class | Status | Inherits | When |
|---|---|---|---|
BadRequestError | 400 | APIStatusError | Malformed payload |
AuthenticationError | 401 | APIStatusError | Bad / expired key |
PermissionDeniedError | 403 | APIStatusError | Key revoked or lacks scope |
NotFoundError | 404 | APIStatusError | Unknown resource |
ConflictError | 409 | APIStatusError | Resource exists (e.g. duplicate org_id) |
UnprocessableEntityError | 422 | APIStatusError | Pydantic validation failure |
RateLimitError | 429 | APIStatusError | Daily quota exceeded |
InternalServerError | 5xx | APIStatusError | Our problem; SDK retried |
APITimeoutError | — | APIConnectionError → APIError | Network or server too slow |
APIConnectionError | — | APIError | DNS, TLS, connection reset |
[APIResponseValidationError] | - | APIError | Server returned an unexpected response |
TexHTTPError (alias of APIStatusError) and TexAuthError (alias of AuthenticationError) are kept for backward compatibility.
Common fields
Per-class details
BadRequestError
Raised when a payload is malformed. Common causes:
- Missing required field on a turn (e.g. no
text) - Invalid
modevalue onrecall - Invalid
session_idvalue. It must be a string.
e.details includes a Pydantic-style loc list that points to the bad field.
AuthenticationError
Status 401. The SDK already tried one JWT refresh before raising.
PermissionDeniedError
Status 403. The credential is valid but lacks scope. This mostly matters for scoped keys. Default keys should not hit this.
NotFoundError
Status 404. You referenced something that does not exist. This is often a stale key_id on DELETE /me/api-keys/{id}.
UnprocessableEntityError
Status 422. FastAPI validation rejected the payload. The SDK builds payloads for you, so this usually means an argument has the wrong type.
RateLimitError
Status 429. The SDK retries on 429 like other transient codes (with exponential backoff and Retry-After honored), so by the time you see this exception the SDK has already exhausted retries.
For daily-quota 429s, retries will not help until midnight UTC. Set max_retries=0 on paths where you would rather fail fast:
e.details payload tells you which cap was exceeded (tokens_in_daily or tokens_out_daily) and when it resets:
InternalServerError
Status 5xx. The SDK already tried the request again with exponential backoff. If you still see this, file a ticket with e.request_id.
APITimeoutError
The request did not return within timeout. The SDK retries timeouts. If every attempt fails, it raises APITimeoutError.
APIConnectionError
DNS, TLS, or socket-level failure. The retry behavior is the same as APITimeoutError. If you see this in production, check your egress proxy or firewall.
Built-in retries
The SDK retries automatically on:- Status codes:
408,429,500,502,503,504 httpx.TimeoutExceptionhttpx.HTTPError(network)
Retry-After. If the server says wait 3 seconds, the SDK waits at least 3 seconds.
Quota
429s retry like other 429s. The retry will still fail if you are over the cap. Set max_retries=0 on quota-sensitive paths if you want to fail faster.Idempotency
remember is idempotent because Tex deduplicates turns by hash. recall and usage.* are read-only. It is safe to retry any of them.
Next: REST API
Direct HTTP integration without the SDK.

