{"record":{"id":"5f93e53bda3d6417","repo":"moeru-ai/airi","slug":"gateway-timeout-service-unavailable-bad-gateway","errorCode":"GATEWAY_TIMEOUT/SERVICE_UNAVAILABLE/BAD_GATEWAY","errorMessage":"Upstream timeout | Upstream rate-limited | Upstream unavailable (selected by last upstream status: 'timeout'->'Upstream timeout', 429->'Upstream rate-limited', other non-2xx->'Upstream unavailable')","messagePattern":"Upstream timeout \\| Upstream rate-limited \\| Upstream unavailable \\(selected by last upstream status: 'timeout'->'Upstream timeout', 429->'Upstream rate-limited', other non-2xx->'Upstream unavailable'\\)","errorType":"exception","errorClass":"ApiError","httpStatus":504,"severity":"error","filePath":"server/apps/api/src/services/domain/llm-router/router.ts","lineNumber":549,"sourceCode":"    const distinctStatuses = new Set(allFailures.map(f => f.status))\n    if (distinctStatuses.size === 1) {\n      const status = allFailures[0].status\n      // Increment per-provider so multi-upstream models still get one\n      // signal per provider involved — operators can see *which* provider\n      // ran the shared-backend cap.\n      const providersHit = new Set(allFailures.map(f => f.provider))\n      for (const provider of providersHit) {\n        options.gatewayMetrics?.sameStatusExhaustion.add(1, {\n          provider,\n          status_code: typeof status === 'number' ? status : 'timeout',\n        })\n      }\n    }\n\n    if (terminalResponse != null)\n      return terminalResponse\n\n    throw mapUpstreamError(\n      lastFailure.status,\n      {\n        triedKeys: allFailures.length,\n        triedUpstreams,\n        lastStatusCode: lastFailure.status,\n      },\n      allFailures.map(toDiagnosticAttempt),\n    )\n  }\n\n  /**\n   * Run one TTS upstream's key list in order, parallel to {@link dispatchOneUpstream}\n   * but delegating actual HTTP to the provider adapter. Adapters surface\n   * upstream non-2xx as {@link TtsUpstreamResponseError}; network failures\n   * and timeouts arrive as errors without an upstream response.\n   */\n  async function dispatchOneTtsUpstream(\n    upstream: TtsUpstream,","sourceCodeStart":531,"sourceCodeEnd":567,"githubUrl":"https://github.com/moeru-ai/airi/blob/f679616c34f1cf6d282c8d64264242af944b3fed/server/apps/api/src/services/domain/llm-router/router.ts#L531-L567","documentation":"Error \"Upstream timeout | Upstream rate-limited | Upstream unavailable (selected by last upstream status: 'timeout'->'Upstream timeout', 429->'Upstream rate-limited', other non-2xx->'Upstream unavailable')\" thrown in moeru-ai/airi.","triggerScenarios":"Thrown at server/apps/api/src/services/domain/llm-router/router.ts:549 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Restore or add healthy upstream providers for the model — every candidate was tried and exhausted","For 429 endings, back off and retry after the provider's rate-limit window resets","For timeout endings, review per-upstream timeout settings and provider health before retrying"],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"f679616c34f1cf6d282c8d64264242af944b3fed","analyzedAt":"2026-09-08T13:18:15.005Z","contentChangedAt":"2026-09-08T13:18:15.005Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}