Skip to content

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.

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.

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’s client_id and client authentication. A username is not a client_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, or unauthorized_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.

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.

  1. Keep one request in flight per feed or selection.
  2. 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.
  3. Honour a valid Retry-After header, but don’t expect one. On 429, lower your request rate instead of waiting and repeating the same burst.
  4. Don’t retry wrong credentials, invalid requests, missing scopes, or compromised credentials. Repeated failed sign-ins can lock an account.
  5. 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.

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 GetBusPosition response is not a vehicle at latitude/longitude zero.
  • A missing arrival or GPS timestamp means no data, not the Unix epoch.
  • stop_order=0 is valid and differs from an absent stop_order.
  • Zero delay or an ON_TIME category 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.
  • 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.