{"record":{"id":"e0343bbf947b2d3a","repo":"HeyPuter/puter","slug":"errtext-xai-stt-request-failed-status-respo","errorCode":null,"errorMessage":"errText || `xAI STT request failed (status ${response.status})`","messagePattern":"errText \\|\\| `xAI STT request failed \\(status (.+?)\\)`","errorType":"http","errorClass":"HttpError","httpStatus":null,"severity":"error","filePath":"src/backend/drivers/ai-speech2txt/providers/xai/XAISpeechToTextProvider.ts","lineNumber":217,"sourceCode":"                `[XAISpeechToTextProvider] API returned ${response.status}: ${errText}`,\n            );\n            // Mirrors ElevenLabs / XAITTS — map upstream status to an\n            // `upstream_*` HttpError so the alarm gate skips it.\n            const legacyCode =\n                response.status >= 500\n                    ? 'upstream_provider_unavailable'\n                    : response.status === 401 || response.status === 403\n                      ? 'upstream_auth_failed'\n                      : response.status === 429\n                        ? 'upstream_rate_limited'\n                        : 'upstream_bad_request';\n            const exposedStatus =\n                legacyCode === 'upstream_rate_limited'\n                    ? 429\n                    : legacyCode === 'upstream_auth_failed'\n                      ? 500\n                      : 400;\n            throw new HttpError(\n                exposedStatus,\n                errText || `xAI STT request failed (status ${response.status})`,\n                {\n                    legacyCode,\n                    fields: {\n                        provider: 'xai',\n                        upstreamStatus: response.status,\n                    },\n                },\n            );\n        }\n\n        const result = await response.json();\n\n        // Meter actual usage using returned duration, or estimated\n        const actualSeconds =\n            typeof result.duration === 'number'\n                ? Math.ceil(result.duration)","sourceCodeStart":199,"sourceCodeEnd":235,"githubUrl":"https://github.com/HeyPuter/puter/blob/908ec23eda38526170322c3edf71ba45ecb1ca95/src/backend/drivers/ai-speech2txt/providers/xai/XAISpeechToTextProvider.ts#L199-L235","documentation":"Surfaced when the upstream xAI /v1/stt call returns a non-2xx response. The provider reads the error body and re-throws an HttpError whose legacyCode maps the upstream status: 5xx -> upstream_provider_unavailable, 401/403 -> upstream_auth_failed (exposed as 500), 429 -> upstream_rate_limited (exposed as 429), other 4xx -> upstream_bad_request (exposed as 400). The message is xAI's errText when present, else a generic 'xAI STT request failed (status N)'. The original upstream status is attached in fields.upstreamStatus.","triggerScenarios":"xAI rejects the transcription: invalid/expired configured API key (401/403), quota exhausted (429), unsupported audio format or malformed multipart (4xx), or an xAI-side outage (5xx). Also triggered by audio exceeding xAI limits or unsupported codecs.","commonSituations":"The configured xAI key was revoked or is for the wrong workspace; a 429 during burst traffic; sending an audio format xAI cannot decode; transient xAI 5xx incidents. The exposed 500 for auth failures often masks the real cause (bad key) since upstream 401 is intentionally hidden.","solutions":["Inspect fields.upstreamStatus and fields.legacyCode in the error: 401/403 -> rotate/fix the configured xAI key; 429 -> slow down or back off; 4xx -> fix the audio payload/format; 5xx -> retry with backoff.","For upstream_rate_limited, implement exponential backoff or queue requests below xAI's rate ceiling.","For upstream_auth_failed, update providers.xai.apiKey with a valid key and restart.","For upstream_bad_request, confirm the audio is under 500MB and in a format xAI accepts (mp3, wav, etc.), and that multipart fields (channels, format, diarize) are valid.","Check server logs for the '[XAISpeechToTextProvider] API returned N: ...' line which carries the full upstream body."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  const t = await driver.transcribe({ provider: 'xai', file });\n} catch (e) {\n  const code = e?.fields?.legacyCode;\n  if (code === 'upstream_rate_limited') {\n    // back off and retry with exponential delay\n  } else if (code === 'upstream_auth_failed') {\n    // alert ops: the configured xAI key is bad/revoked\n  } else if (code === 'upstream_provider_unavailable') {\n    // transient xAI outage — retry a limited number of times\n  } else if (code === 'upstream_bad_request') {\n    // fix the audio payload/format; check fields.upstreamStatus for detail\n  } else throw e;\n}","preventionTips":["Branch on fields.legacyCode rather than the HTTP status alone — the exposed status is remapped.","Inspect fields.upstreamStatus for the real xAI code (401/403 there means the configured key is invalid).","Keep audio within xAI's documented size/format limits to avoid upstream_bad_request.","Check server logs for the full upstream body when the message is generic."],"tags":["upstream","xai","speech-to-text","network","rate-limit","auth"],"backgroundTag":null,"analyzedSha":"908ec23eda38526170322c3edf71ba45ecb1ca95","analyzedAt":"2026-08-12T20:53:15.911Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}