Errors and retries
Identity returns OAuth or JSON errors, GTFS-RT returns HTTP status codes, and Frontline returns gRPC statuses, plus possible HTTP transport errors.
HTTP status codes
Section titled “HTTP status codes”| Status | Meaning and action |
|---|---|
200 |
Check the content type. A GTFS feed must decode as protobuf, not JSON or HTML. |
304 |
GTFS conditional request: unchanged, no body. Keep your current data. |
400 |
Fix missing fields, malformed proof, or an ineligible account or ceremony. Check the JSON body if present. |
401 |
Check token expiry, issuer, audience, or client authentication. Renew instead of repeating a bad token. |
403 |
Authenticated but not allowed. Check the scope or application permissions; retrying won’t help. |
404 |
Check the origin, path, and identifier. Some unknown Frontline entities return empty data instead. |
418 |
I’m a teapot. The server is steeping your request. Wait 3–5 minutes, add milk, and retry. Biscuits don’t count toward your rate limit. |
429 |
Rate limited. Slow down every worker sharing the identity or IP; see rate limits. |
503 |
GTFS has no fresh feed, or an Identity ceremony is temporarily unavailable. Back off, and restart one-time ceremonies. |
Other 5xx |
A service failure, not data. Retry reads a limited number of times and report persistent failures. |
Error bodies aren’t guaranteed; a GTFS 503 can be empty. Never decode a failed
download as a feed.
OAuth and account errors
Section titled “OAuth and account errors”Token requests return error and error_description, as in this synthetic
example:
{ "error": "invalid_grant", "error_description": "Invalid or expired challenge."}invalid_client: check the application’sclient_idand client authentication. A username is not aclient_id.invalid_grant: the proof, challenge, assertion token, refresh token, or account state isn’t valid. Sign in again or start a new ceremony; never replay a used proof.invalid_request,unsupported_grant_type, orunauthorized_client: fix the request, or confirm the application may use that endpoint and grant.temporarily_unavailable: back off and start the ceremony over.
Account and passkey endpoints return error plus message instead, for example
session_expired, no_passkeys, unknown_credential, credential_compromised,
and totp_already_verified. consumer_provisioning_disabled rejects new consumer
setup; it doesn’t mean existing consumers can’t sign in. Malformed requests can
return a validation-problem document. Don’t assume one error schema or exact
wording.
Frontline gRPC status codes
Section titled “Frontline gRPC status codes”| Status | Action |
|---|---|
INVALID_ARGUMENT (3) |
Fix the request, such as a blank stop code or invalid stream identifier. |
NOT_FOUND (5) |
Check the service, direction, or stop identifier. An empty vehicle position is not NOT_FOUND. |
PERMISSION_DENIED (7) |
The token lacks frontline:consumer; retrying won’t fix it. |
RESOURCE_EXHAUSTED (8) |
Close unused streams and reduce concurrency before reconnecting. |
UNIMPLEMENTED (12) |
Check the full method path and transport against the consumer schema. |
UNAVAILABLE (14), DEADLINE_EXCEEDED (4) |
Retry eligible reads with backoff; reconnect streams as new subscriptions. |
UNAUTHENTICATED (16) |
Get a valid access token and send it as bearer metadata. |
CANCELLED (1) |
Expected when you close a stream; don’t reconnect a closed view. |
INTERNAL (13), UNKNOWN (2) |
Check the sanitized status details and report persistent failures. |
Judge success by the gRPC status and trailers, not HTTP 200. A rate-limit 429
can be returned before the RPC runs, and your client may report it as a transport
error instead of RESOURCE_EXHAUSTED. gRPC-Web clients must parse gRPC-Web status
framing.
Retry and backoff
Section titled “Retry and backoff”- Keep one request in flight per feed or selection.
- Retry eligible reads and lost streams with exponential backoff, jitter, a maximum delay, and a retry budget. Stop when the view or job is cancelled, and don’t retry in a burst at a window boundary.
- Honour a valid
Retry-Afterheader, but don’t expect one. On429, lower your request rate instead of waiting and repeating the same burst. - Don’t retry wrong credentials, invalid requests, missing scopes, or compromised credentials. Repeated failed sign-ins can lock an account.
- A timed-out token, passkey, or credential request has an unknown outcome and may have used up a one-time proof. Restart the ceremony or check its state instead of replaying it, and refresh tokens one request at a time.
After reconnecting a Frontline stream, use its new initial snapshot. Missed updates are not replayed.
Absent is not zero
Section titled “Absent is not zero”Protobuf scalar fields that aren’t optional read as zero, false, or empty when
unset. That doesn’t mean a value was measured. Message and optional fields track
presence; use your generated client’s presence checks.
- An empty
GetBusPositionresponse is not a vehicle at latitude/longitude zero. - A missing arrival or GPS timestamp means no data, not the Unix epoch.
stop_order=0is valid and differs from an absentstop_order.- Zero delay or an
ON_TIMEcategory alone doesn’t prove a schedule match; check the schedule and arrival fields. - Declared but unpopulated next-stop and ETA fields don’t signal an imminent arrival. See Frontline limitations.
Token safety
Section titled “Token safety”- Use the approved HTTPS origins. Never disable certificate verification to work around an authentication failure.
- Keep secrets and private keys on a trusted server. A web bundle or mobile app can’t keep a client secret confidential, and a public-key client still needs its private key protected.
- Keep browser access tokens short-lived and out of persistent JavaScript-readable storage. Prefer a server-side session where you can, and agree on browser origins and transports before integrating.
- Never log refresh tokens, TOTP setup secrets, recovery codes, nonces, or assertion tokens, or put them in URLs or support tickets.
- Turn off shell tracing and avoid capturing command output when running the examples; shell variables don’t hide secrets from process listings.
- On sign-out, clear local session data and revoke tokens where you can. A revoked JWT may still be accepted by transit APIs until it expires.
When reporting a failure, include the service, method or path, UTC time, HTTP or gRPC status, and a sanitized error code. Leave out bearer headers, passwords, token bodies, private keys, and personal account details.