{"record":{"id":"37d90ffd6b600dcb","repo":"decolua/9router","slug":"openrouter-tts-returned-no-audio-data","errorCode":null,"errorMessage":"OpenRouter TTS returned no audio data","messagePattern":"OpenRouter TTS returned no audio data","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"open-sse/handlers/ttsProviders/openrouter.js","lineNumber":70,"sourceCode":"    let buffer = \"\";\n\n    while (true) {\n      const { done, value } = await reader.read();\n      if (done) break;\n      buffer += decoder.decode(value, { stream: true });\n      const lines = buffer.split(\"\\n\");\n      buffer = lines.pop();\n      for (const line of lines) {\n        if (!line.startsWith(\"data: \") || line === \"data: [DONE]\") continue;\n        try {\n          const json = JSON.parse(line.slice(6));\n          const audioData = json.choices?.[0]?.delta?.audio?.data;\n          if (audioData) chunks.push(audioData);\n        } catch {}\n      }\n    }\n\n    if (chunks.length === 0) throw new Error(\"OpenRouter TTS returned no audio data\");\n    return { base64: chunks.join(\"\"), format: \"wav\" };\n  },\n};\n","sourceCodeStart":52,"sourceCodeEnd":74,"githubUrl":"https://github.com/decolua/9router/blob/90b52e06ffd666b7929554211474d01588f6b1f8/open-sse/handlers/ttsProviders/openrouter.js#L52-L74","documentation":"After a successful HTTP response, the OpenRouter TTS handler parses the SSE stream and collects base64 audio chunks from choices[0].delta.audio.data. If zero chunks were collected, it throws this error. This can happen when the stream contains only text deltas, errors, or an immediate [DONE].","triggerScenarios":"OpenRouter returns 200 with an SSE stream that never includes delta.audio.data: the model produced no audio (modality not enabled for the model, 'audio' param rejected silently), stream closed early, or chunks arrive in a different JSON shape after an API change.","commonSituations":"Selecting an OpenRouter model that doesn't actually support audio output, account without audio modality access, upstream provider outage mid-stream, or OpenRouter changing the delta payload shape.","solutions":["Verify the chosen model supports audio output modality on OpenRouter and include modality/audio params correctly","Log the raw SSE lines to inspect the actual delta shape","Confirm your OpenRouter account has access to audio-capable models","Try a different TTS model/voice to isolate model-side issues","Check OpenRouter status page for provider outages"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"const res = await fetch(\"https://openrouter.ai/api/v1/models\");\nconst models = (await res.json()).data.map(m => m.id);\nif (!models.includes(ttsModel)) throw new Error(`Model ${ttsModel} not available on OpenRouter`);","typeGuard":"function sseHasAudioChunk(line) {\n  try {\n    const j = JSON.parse(line.replace(/^data: /, \"\"));\n    return typeof j?.choices?.[0]?.delta?.audio?.data === \"string\" && j.choices[0].delta.audio.data.length > 0;\n  } catch { return false; }\n}","tryCatchPattern":"try {\n  return await openrouterTts.synthesize(text, model, creds);\n} catch (e) {\n  if (e.message === \"OpenRouter TTS returned no audio data\") {\n    logger.warn(\"openrouter tts: empty audio stream, falling back\", { model });\n    return fallbackTts(text);\n  }\n  throw e;\n}","preventionTips":["Check the model's supported modalities on OpenRouter before enabling TTS routing","Log raw SSE lines at debug level to detect payload-shape changes early","Treat empty-audio as retriable once, then fall back to another provider","Subscribe to OpenRouter changelog/status for audio API changes"],"tags":["tts","openrouter","sse","empty-response"],"backgroundTag":"empty-response-body","analyzedSha":"90b52e06ffd666b7929554211474d01588f6b1f8","analyzedAt":"2026-08-30T21:05:45.952Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}