{"record":{"id":"94d4af51664ed857","repo":"babysor/MockingBird","slug":"kokoro-tts-failed-for-cue-cue-index-proc-stder","errorCode":null,"errorMessage":"kokoro-tts failed for cue {cue.index}: {proc.stderr}","messagePattern":"kokoro-tts failed for cue (.+?): (.+?)","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"skills/speak/scripts/render_timeline.py","lineNumber":342,"sourceCode":"        tmp.write(cue.text)\n        tmp_path = tmp.name\n\n    try:\n        cmd = [\"kokoro-tts\", tmp_path, str(out_path)]\n        voice = cfg.get(\"voice\")\n        if voice:\n            cmd += [\"--voice\", str(voice)]\n        lang = cfg.get(\"lang\")\n        if lang:\n            cmd += [\"--lang\", str(lang)]\n        speed = cfg.get(\"speed\")\n        if speed is not None:\n            cmd += [\"--speed\", str(speed)]\n        cmd += [\"--format\", output_format]\n\n        proc = subprocess.run(cmd, capture_output=True, text=True)\n        if proc.returncode != 0:\n            raise RuntimeError(\n                f\"kokoro-tts failed for cue {cue.index}: {proc.stderr}\"\n            )\n    finally:\n        Path(tmp_path).unlink(missing_ok=True)\n\n    if out_path.exists():\n        return probe_duration_ms(out_path) / 1000.0\n    raise RuntimeError(f\"kokoro-tts produced no output for cue {cue.index}\")\n\n\n# ── main ─────────────────────────────────────────────────────────────\n\n\ndef main() -> int:\n    ap = argparse.ArgumentParser(\n        description=\"Render timeline-accurate speech from SRT.\"\n    )\n    ap.add_argument(\"--srt\", required=True, help=\"Input SRT file\")","sourceCodeStart":324,"sourceCodeEnd":360,"githubUrl":"https://github.com/babysor/MockingBird/blob/28dc5e14f12d7c754612af2fde8e78a4b03f8616/skills/speak/scripts/render_timeline.py#L324-L360","documentation":"RuntimeError raised in _kokoro_tts when the kokoro-tts subprocess exits non-zero for a cue; its stderr is captured and embedded. The command is built from cue text, voice, speed, and output format, then run against a temp script file.","triggerScenarios":"Cue text containing characters that break the temp input handling, an invalid voice name or unsupported --format value, model files not downloaded, or speed out of the CLI's accepted range.","commonSituations":"First run before model weights are fetched, emoji/unicode in subtitle lines, or format strings like 'mp3' where the build only supports wav.","solutions":["Run kokoro-tts manually with the same args to see full stderr","Pre-download/verify model assets per the CLI's docs","Sanitize cue text (strip emoji/control chars) before rendering","Use a supported --format value (e.g. wav)"],"exampleFix":"# before\ntext = cue.text\n# after\nimport re\ntext = re.sub(r'[\\U0001F000-\\U0001FAFF\\u2600-\\u27BF]', '', cue.text).strip()","handlingStrategy":"try-catch","validationCode":"import re\nclean = re.sub(r'[^\\S\\n ]+', '', cue.text).strip()\nassert clean, f'cue {cue.index} has no speakable text'","typeGuard":null,"tryCatchPattern":"try:\n    _kokoro_tts(cue, cfg, fmt, ...)\nexcept RuntimeError as e:\n    print(f'cue {cue.index} failed: {e}')\n    raise if not cfg.get('skip_failed_cues') else None","preventionTips":["Sanitize cue text (emoji/control chars)","Pre-download model assets","Test the CLI manually with a sample cue"],"tags":["kokoro","subprocess","tts","rendering"],"backgroundTag":"subprocess-nonzero-exit","analyzedSha":"28dc5e14f12d7c754612af2fde8e78a4b03f8616","analyzedAt":"2026-08-27T02:26:53.589Z","schemaVersion":2},"datasetVersion":"2026-08-27T03:17:27.898Z"}