Console
Sign in
Browse docs
On this page
  1. Before you start
  2. Steps
  3. 1. Capture the answer and its request ID
  4. 2. Find which service answered
  5. 3. Trace the request through the logs
  6. 4. Check the services' health
  7. 5. Ask Access the gateway's question
  8. 6. Look the answer up
  9. Check that it worked
  10. If something goes wrong
  11. Related

Troubleshoot a request

Follow one failing request across the platform: read what came back, work out which service produced it, trace it through the logs by its request ID, and jump to the troubleshooting entry that fixes it. Developers start here when a call fails (developer); operators start here when a user reports a request ID (sysops).

Read byPlatform operatorApplication developerConsole and CLI user

Before you start#

You needWhy
The full response: status line, headers and body (curl -i, the browser's network panel, or the console's refusal panel)The status alone is ambiguous: several services use the same numbers
Read access to the gateway, Access and Data logsEach service logs the reason it never sends to the caller
The metrics token for each service, if you want counters/metrics answers 404 or 401 without it
platformctl with a profile for the deployment (optional)status, doctor and access decide shorten the search (CLI usage)

Steps#

1. Capture the answer and its request ID#

Every gateway answer carries x-request-id, and the same ID is on every gateway log line of that request. Copy it together with the status, the body and any retry-after header.

You can choose the ID yourself when you reproduce the problem: the gateway keeps a caller's x-request-id when it matches ^[A-Za-z0-9._-]{1,64}$ and replaces anything else with a UUID (gateway spec §2.1). The CLI sends one with --request-id:

bash
curl -s -i -H 'x-request-id: repro-001' "https://api.example.com/ws/<workspace>/v1/me" -H "cookie: $SESSION"
platformctl --request-id repro-002 --verbose data me

When the console refuses something, its page shows the status, the code, the message and the request ID (console user guide).

2. Find which service answered#

Read the body before the status. Each service has its own error shape, and the gateway forwards an upstream's body untouched (gateway spec §2.3):

BodyAnswered byCodes are listed in
{"error": "no_route", "message": "…"}: a string error, lower-case codeThe gateway itselfgateway spec §2.5
{"error": {"code": "FORBIDDEN", "message": "…"}, "requestId": "…"}: an object error, upper-case codeData, forwarded by the gatewaydata spec §9.7
Empty, with status 499Nobody: the caller left before the headersgateway spec §11.3
Any other shapeAnother upstream, forwarded unchangedThat service's own docs
A login page with a status and a code, on Access's addressAccess, during sign-inAccess troubleshooting: failed logins
{"error": "<code>", "message": "…"} from Access's own addressAccess administration or a contract endpoint, called directlyAccess troubleshooting
A message on standard error and an exit statusThe CLI, reporting a service's refusalCLI spec §6.2

An Access decision never reaches the caller as such: the gateway turns it into its own 403 workspace_forbidden or 503 access_unavailable and keeps the reason out of the answer (gateway spec §6).

3. Trace the request through the logs#

  1. Search the gateway logs for the request ID. The line names the route, the caller's subject, the workspace and the trace ID (gateway spec §12.2).
  2. The gateway sends the upstream a traceparent with that trace ID, so an upstream that logs trace context can be searched with it (gateway spec §7.5).
  3. For Data, look up the gateway's request ID in the Data log (Data troubleshooting: gateway answers 502). A Data error body also carries requestId, the identifier Data's own log lines use (data spec §15.2).
  4. For a 403 workspace_forbidden, read Access's decision log line for the same subject, workspace and route: it holds the reason and its code (Access troubleshooting: decisions denied).

If the gateway logs have no line for the ID, the request never reached the gateway, or it reached it with a malformed ID that was replaced: check the ingress first.

4. Check the services' health#

Rule out an outage before you debug one request:

bash
platformctl status          # health and readiness of the services in the profile; --watch repeats every 5 s
platformctl doctor          # also checks the profile and your credential

Both end with exit status 7 when a service does not answer (CLI spec §5.1). Without the CLI, read each service's /readyz body: the gateway reports its route table and session store (gateway spec §12.3), and Data gives a reason (data spec §15.1). The console's Status page shows the same probes (console user guide).

5. Ask Access the gateway's question#

For any refusal that involves a caller's rights, ask Access directly with the subject, workspace and route from the gateway's log line. A denial ends with exit status 6:

bash
platformctl access decide --subject <principal id> --workspace <workspace uuid> --route <route id>

6. Look the answer up#

Find the status and code in this table, then follow the link. Codes in lower case come from the gateway, codes in upper case from Data.

Status and codeWhat it usually meansGo to
302 to /auth/loginA browser without a valid session on a route that accepts onegateway spec §5.2
400 bad_requestThe workspace placeholder is missing or not a UUIDGateway troubleshooting
400 login_failedThe login callback could not completeGateway troubleshooting
400 INVALID_QUERY, INVALID_REQUEST, INVALID_CURSOR, INVALID_PRECONDITIONData refused the query, body, cursor or if-matchdata spec §9.3, §9.4, §9.5
401 unauthorizedNo valid credential for the route's modeGateway troubleshooting
401 UNAUTHENTICATEDData could not verify the gateway's signature, or the call bypassed the gatewayData troubleshooting
403 workspace_forbiddenAccess denied the caller the workspace on this routeGateway troubleshooting, Access: decisions denied
403 cross_site_requestA request with the session cookie came from a site that is not allowedGateway troubleshooting
403 FORBIDDENThe gateway let the caller in, but Data's context or policies refuse the actionData troubleshooting
403 identity_unknown and other login-page codesAccess refused the sign-inAccess troubleshooting
404 no_routeNo route matches the host, path and methodGateway troubleshooting
404 not_foundThe path is reserved by the gatewayGateway troubleshooting
404 NOT_FOUNDUnknown or disabled workspace, a collection the workspace does not serve, or a record out of reachData troubleshooting
409 CONFLICT, IDEMPOTENCY_CONFLICT, OPERATION_IN_PROGRESS, CURSOR_STALEA concurrent write, a reused key, a create still running, or an outdated cursorData troubleshooting
409 from the control planeStale If-Match, or a protected routeGateway troubleshooting
412 PRECONDITION_FAILEDThe record changed after you read its etagData troubleshooting
413 payload_too_largeThe body is over the route's limitGateway troubleshooting
422 VALIDATION_FAILED, INVALID_REFERENCEThe record does not fit the manifest, or a reference is not readabledata spec §9.7
422 RESULT_TOO_LARGEThe page or its expansions passed Data's budgetData troubleshooting
422 from the control planeThe route table is invalidGateway troubleshooting
428 PRECONDITION_REQUIREDAn update, delete or rollback without if-matchdata spec §9.4
429 too_many_requestsA gateway rate limit; wait for retry-afterGateway troubleshooting
429 TOO_MANY_REQUESTSThe tenant used its share of Data's concurrent requestsData troubleshooting
500 internal_errorThe subject cannot be written to a headerGateway troubleshooting
500 INTERNAL_ERRORA Data defect; report it with the request IDdata spec §9.7
502 bad_gatewayThe upstream was unreachable, refused TLS, or broke the exchangeGateway troubleshooting, Data troubleshooting
503 not_readyThe gateway never loaded a route tableGateway troubleshooting
503 gateway_overloadedAdmission or the exchange cap is full, usually behind a slow dependencyGateway troubleshooting
503 access_unavailableThe gateway could not get a decision from AccessGateway troubleshooting, Access: outages
503 identity_provider_unavailable, session_store_unavailableSign-in cannot reach the provider or store the sessionGateway troubleshooting
503 AUTHORIZATION_UNAVAILABLEData could not get a usable access context from AccessData troubleshooting
503 DATABASE_UNAVAILABLEData cannot reach its database or registryData troubleshooting
503 OVERLOADED, DRAININGThe Data process is full, or shutting downData configuration: budgets, Data operations: drain
504 gateway_timeoutThe upstream sent no headers within the route's responseMsGateway troubleshooting
504 DEADLINE_EXCEEDEDA Data statement ran over its budgetData troubleshooting

Two pairs are easy to confuse. A 403 workspace_forbidden comes before the request reaches Data: Access found no live grant for that workspace and route, or the principal or tenant is disabled. A 403 FORBIDDEN comes from Data, often for a caller who does hold a grant whose permission keys no policy maps to the requested action (data spec §2.3). And with default settings, the gateway gives up on an upstream after 5 seconds while Data allows a request 10 seconds (DATA_REQUEST_TIMEOUT_MS), so a slow Data call usually surfaces as the gateway's 504 gateway_timeout.

Check that it worked#

  1. Send the same request again with a fresh x-request-id and confirm the status you expect.
  2. Find that ID in the gateway log and, for Data routes, in the Data log, with no refusal line.
  3. Watch the counter that matched the symptom stop rising, for example gateway_auth_failures_total, gateway_access_unavailable_total or data_authorization_denials_total (Gateway troubleshooting: start here, Data operations: metrics).
  4. platformctl doctor ends with exit status 0.

If something goes wrong#

SymptomLook here
No gateway log line carries the request IDGateway operations: ingress
The status is not in the table abovegateway spec §2.5, data spec §9.7, Access troubleshooting
platformctl refuses before sending anythingCLI usage: when something refuses
A WebSocket closes with 1008 or 1001Gateway troubleshooting: connections close
Every caller fails at onceMonitor the platform, Respond to an incident