Skip to content

Errors

External API errors return a small JSON envelope:

{
"error": "no_online_device",
"message": "No user device is currently online."
}

error is a stable machine-readable code; message (when present) is human-readable. Some errors carry extra fields — insufficient_scope includes a required array of the missing scopes.

HTTPerrorMeaning / what to do
400invalid_request, unknown_scope, no_scopes, invalid_url, no_eventsMalformed input — fix before retrying. Schema validation failures return code FST_ERR_VALIDATION.
401missing_tokenNo Authorization: Bearer header.
401invalid_tokenExpired, revoked, malformed, or the app/grant was disabled.
403account_unavailableThe account is suspended.
403insufficient_scopeToken lacks a required scope (see required).
403pat_only_scopemachines:invoke was called with an OAuth token — it requires a PAT.
403rejectedThe target device declined the relay request (e.g. per-app policy).
403no_content_grantContent endpoint called without a key grant for the resource.
404not_foundResource doesn’t exist or isn’t yours.
409session_inactiveTarget session is not active.
409machine_offlineTarget machine is not online.
429rate_limitedQuota exceeded — honor Retry-After and the X-RateLimit-* headers.
502errorThe device reported an internal failure handling the relay.
503no_online_deviceNo device online to serve the relay. Comes with Retry-After: 30.
504timeoutDevice didn’t reply within 30 s. The operation may still have applied — check before blindly retrying.

The OAuth protocol endpoints (/oauth/token, /oauth/revoke, /oauth/introspect) use the RFC 6749 shape instead:

{ "error": "invalid_grant", "error_description": "…" }

Codes: invalid_request, invalid_client, invalid_grant, unauthorized_client, unsupported_grant_type, invalid_scope, unsupported_response_type, server_error. Note that refresh-token reuse surfaces as invalid_grant and revokes the whole grant — the user must re-consent.

Anything unexpected returns the global shape with details masked:

{
"error": "Internal Server Error",
"message": "An unexpected error occurred",
"code": "internal_error",
"statusCode": 500
}
  • 429 — back off exponentially; respect Retry-After.
  • 503 no_online_device — retry after the Retry-After window once a device is up; this is the normal “laptop is asleep” case.
  • 504 timeout — verify state before retrying non-idempotent relays.
  • 500 — retry once with backoff; if it persists, report the requestId.
  • Everything else is terminal — fix the request instead of retrying.