HeyPuter/puter · error · HttpError
errText || `xAI STT request failed (status ${response.status
Error message
errText || `xAI STT request failed (status ${response.status})` What it means
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.
Source
Thrown at src/backend/drivers/ai-speech2txt/providers/xai/XAISpeechToTextProvider.ts:217
`[XAISpeechToTextProvider] API returned ${response.status}: ${errText}`,
);
// Mirrors ElevenLabs / XAITTS — map upstream status to an
// `upstream_*` HttpError so the alarm gate skips it.
const legacyCode =
response.status >= 500
? 'upstream_provider_unavailable'
: response.status === 401 || response.status === 403
? 'upstream_auth_failed'
: response.status === 429
? 'upstream_rate_limited'
: 'upstream_bad_request';
const exposedStatus =
legacyCode === 'upstream_rate_limited'
? 429
: legacyCode === 'upstream_auth_failed'
? 500
: 400;
throw new HttpError(
exposedStatus,
errText || `xAI STT request failed (status ${response.status})`,
{
legacyCode,
fields: {
provider: 'xai',
upstreamStatus: response.status,
},
},
);
}
const result = await response.json();
// Meter actual usage using returned duration, or estimated
const actualSeconds =
typeof result.duration === 'number'
? Math.ceil(result.duration)View on GitHub (pinned to 908ec23eda)
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.
Defensive patterns
Strategy: try-catch
Try / catch
try {
const t = await driver.transcribe({ provider: 'xai', file });
} catch (e) {
const code = e?.fields?.legacyCode;
if (code === 'upstream_rate_limited') {
// back off and retry with exponential delay
} else if (code === 'upstream_auth_failed') {
// alert ops: the configured xAI key is bad/revoked
} else if (code === 'upstream_provider_unavailable') {
// transient xAI outage — retry a limited number of times
} else if (code === 'upstream_bad_request') {
// fix the audio payload/format; check fields.upstreamStatus for detail
} else throw e;
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- upstreamMessage ?? `ElevenLabs request failed (status ${resp
- ElevenLabs returned ${response.status}
- internal_error
- insufficient_funds
- App not found
AI-assisted analysis of HeyPuter/puter@908ec23eda (2026-08-12).
Data as JSON: /api/errors/e0343bbf947b2d3a.
Report an issue: GitHub.