babysor/MockingBird · error · RuntimeError
/text-to-speech cue {cue.index}: status={resp.status_code},
Error message
/text-to-speech cue {cue.index}: status={resp.status_code}, body={resp.text} What it means
RuntimeError raised in _noiz_tts when the per-cue /text-to-speech request returns non-200. The cue index and response body identify which subtitle line failed and why, so a multi-cue render pinpoints the failure.
Source
Thrown at skills/speak/scripts/render_timeline.py:298
}
elif not cfg.get("voice_id"):
raise ValueError(
f"Cue {cue.index}: either voice_id or reference_audio required."
)
try:
resp = requests.post(
url, headers={"Authorization": api_key},
data=payload, files=files, timeout=timeout,
)
finally:
if files and files["file"][1]:
files["file"][1].close()
if ref_cleanup is not None:
ref_cleanup.unlink(missing_ok=True)
if resp.status_code != 200:
raise RuntimeError(
f"/text-to-speech cue {cue.index}: "
f"status={resp.status_code}, body={resp.text}"
)
out_path.write_bytes(resp.content)
dur_h = resp.headers.get("X-Audio-Duration")
return float(dur_h) if dur_h else -1.0
# ── Kokoro backend ───────────────────────────────────────────────────
def _ensure_kokoro() -> None:
if not shutil.which("kokoro-tts"):
raise RuntimeError("kokoro-tts CLI not found.")
def _kokoro_tts(
cue: Cue,View on GitHub (pinned to 28dc5e14f1)
Solutions
- Use the cue index in the message to find the offending subtitle line
- Apply the body's guidance: shorten text, fix voice config, or back off for 429
- Add per-cue retry with backoff
- Cache successful cues so reruns skip completed ones
Example fix
# before
seg = _noiz_tts(cue, cfg, fmt, ...)
# after
for attempt in range(3):
try:
seg = _noiz_tts(cue, cfg, fmt, ...)
break
except RuntimeError:
if attempt == 2: raise
time.sleep(2 ** attempt) Defensive patterns
Strategy: retry
Validate before calling
assert len(cue.text) <= 5000, f'cue {cue.index} too long' Try / catch
for attempt in range(3):
try:
seg = _noiz_tts(cue, cfg, fmt, ...); break
except RuntimeError as e:
if attempt == 2 or 'status=4' in str(e) and '429' not in str(e): raise
time.sleep(2 ** attempt) Prevention
- Retry per-cue with backoff; skip-and-report strategy for batch renders
- Cache rendered segments for resume
- Watch the cue index in errors
When it happens
Trigger: A cue with text over the char limit, invalid voice_id/reference for that cue, auth failure, or rate limiting after many sequential requests.
Common situations: One overly long subtitle line, a voice-map entry with an expired/invalid voice id, or 429s during a large timeline render.
Related errors
- /text-to-speech failed: status={resp.status_code}, body={res
- /emotion-enhance failed: status={resp.status_code}, body={re
- /emotion-enhance failed: status={resp.status_code}, body={re
- /emotion-enhance returned no data: {resp.text}
- /emotion-enhance returned no data: {resp.text}
AI-assisted analysis of babysor/MockingBird@28dc5e14f1 (2026-08-27).
Data as JSON: /api/errors/aff024bf2abc0f97.
Report an issue: GitHub.