{"record":{"id":"84d615c697817773","repo":"decolua/9router","slug":"inworld-tts-returned-no-audio","errorCode":null,"errorMessage":"Inworld TTS returned no audio","messagePattern":"Inworld TTS returned no audio","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"open-sse/handlers/ttsProviders/genericFormats.js","lineNumber":87,"sourceCode":"  if (!res.ok) await throwUpstreamError(res);\n  return responseToBase64(res, \"mp3\");\n}\n\n// Inworld: Basic auth, JSON { audioContent }\nasync function inworld({ baseUrl, apiKey, text, modelId, voiceId }) {\n  const res = await fetch(baseUrl, {\n    method: \"POST\",\n    headers: { \"Content-Type\": \"application/json\", \"Authorization\": `Basic ${apiKey}` },\n    body: JSON.stringify({\n      text,\n      voiceId: voiceId || \"Alex\",\n      modelId: modelId || \"inworld-tts-1.5-mini\",\n      audioConfig: { audioEncoding: \"MP3\" },\n    }),\n  });\n  if (!res.ok) await throwUpstreamError(res);\n  const data = await res.json();\n  if (!data.audioContent) throw new Error(\"Inworld TTS returned no audio\");\n  return { base64: data.audioContent, format: \"mp3\" };\n}\n\n// Cartesia: X-API-Key header\nasync function cartesia({ baseUrl, apiKey, text, modelId, voiceId }) {\n  const res = await fetch(baseUrl, {\n    method: \"POST\",\n    headers: {\n      \"Content-Type\": \"application/json\",\n      \"X-API-Key\": apiKey,\n      \"Cartesia-Version\": \"2024-06-10\",\n    },\n    body: JSON.stringify({\n      model_id: modelId || \"sonic-2\",\n      transcript: text,\n      ...(voiceId ? { voice: { mode: \"id\", id: voiceId } } : {}),\n      output_format: { container: \"mp3\", bit_rate: 128000, sample_rate: 44100 },\n    }),","sourceCodeStart":69,"sourceCodeEnd":105,"githubUrl":"https://github.com/decolua/9router/blob/90b52e06ffd666b7929554211474d01588f6b1f8/open-sse/handlers/ttsProviders/genericFormats.js#L69-L105","documentation":"The Inworld TTS handler POSTs `{ input, modelId, audioConfig:{audioEncoding:'MP3'} }` to Inworld's endpoint. After a 2xx response it requires the `audioContent` field (base64 MP3) in the JSON body; if absent it throws this error. It means Inworld acknowledged the request but did not return audio in the expected field.","triggerScenarios":"Upstream returns 200 with a JSON body lacking `audioContent` — e.g. response shape changed (API version drift), or an error/muted/empty payload embedded in a 200 response.","commonSituations":"Inworld API contract change (field renamed or nested differently); account/voice misconfiguration returning a silent empty response; proxy/gateway returning a 200 HTML or JSON error envelope instead of the TTS payload.","solutions":["Log the raw response body at this point to see what Inworld actually returned","Verify the Inworld TTS endpoint URL and payload schema against current docs (field may now be nested, e.g. `result.audioContent`)","Check the voice ID / API key / quota — some Inworld errors come back as 200 with a message field instead of audio","Pin/upgrade to the current Inworld API version and update the handler if the field moved"],"exampleFix":"// before\nconst data = await res.json();\nif (!data.audioContent) throw new Error('Inworld TTS returned no audio');\n// after (tolerate nested shape)\nconst data = await res.json();\nconst b64 = data.audioContent ?? data.result?.audioContent ?? data.audio?.audioContent;\nif (!b64) throw new Error('Inworld TTS returned no audio: ' + JSON.stringify(data).slice(0, 200));","handlingStrategy":"try-catch","validationCode":"if (!text || typeof text !== 'string') throw new Error('text required for Inworld TTS');","typeGuard":"const hasAudio = (d) => d != null && typeof d === 'object' && typeof d.audioContent === 'string' && d.audioContent.length > 0;","tryCatchPattern":"try { return await inworldTts(...); } catch (e) { if (e.message.includes('no audio')) { logger.warn('inworld empty payload'); return fallbackTts(...); } throw e; }","preventionTips":["Log the raw Inworld response when this fires to detect schema drift early","Pin the Inworld API version and review changelogs","Keep a fallback TTS provider configured"],"tags":["tts","inworld","api-contract","upstream"],"backgroundTag":"empty-response-body","analyzedSha":"90b52e06ffd666b7929554211474d01588f6b1f8","analyzedAt":"2026-08-30T21:05:45.952Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}