{"record":{"id":"1176768f993b5c78","repo":"heygen-com/hyperframes","slug":"speech-synthesis-failed-detail","errorCode":null,"errorMessage":"Speech synthesis failed${detail}","messagePattern":"Speech synthesis failed(.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/cli/src/tts/synthesize.ts","lineNumber":209,"sourceCode":"      sampleRate: result.sampleRate,\n      durationSeconds: result.durationSeconds,\n      langApplied: result.langApplied,\n    };\n  } catch (err: unknown) {\n    // If the error is our own JSON parse failure but the file was created,\n    // re-throw with a clearer message rather than returning fabricated data\n    if (err instanceof SyntaxError && existsSync(outputPath)) {\n      throw new Error(\n        \"Speech was generated but metadata could not be read. Check the output file manually.\",\n      );\n    }\n\n    let detail = \"\";\n    if (err && typeof err === \"object\" && \"stderr\" in err) {\n      const stderr = String(err.stderr).trim();\n      if (stderr) detail = `\\n${stderr.slice(-500)}`;\n    }\n    throw new Error(`Speech synthesis failed${detail}`);\n  }\n}\n","sourceCodeStart":191,"sourceCodeEnd":212,"githubUrl":"https://github.com/heygen-com/hyperframes/blob/c2996c8626135db5253519359d8a063d3bafad8d/packages/cli/src/tts/synthesize.ts#L191-L212","documentation":"The catch-all at the end of synthesize()'s try block. Fires when execFileSync threw a non-SyntaxError (i.e. the Python process exited non-zero, was killed by the 300s timeout, or could not be spawned), OR when JSON.parse threw but the output file does NOT exist (so it is not the [244] path). detail appends the last 500 chars of stderr when present on the thrown error object, so the message usually carries the Python traceback.","triggerScenarios":"Python raised during model load (corrupt/missing Kokoro model file), during phonemization (unsupported voice id, espeak-ng missing for non-English lang), OOM during inference, the 300_000ms execFileSync timeout fired, or the model/voices paths passed in argv do not exist. Any unhandled Python exception produces a non-zero exit → this error.","commonSituations":"First-run model download was interrupted leaving a truncated .onnx; voice id not present in voices.bin; espeak-ng not installed on the system for Mandarin/other non-English langs; very long input text exceeding memory; a GPU/CPU mismatch in onnxruntime causing a crash at inference.","solutions":["Read the detail (last 500 chars of stderr) — it carries the Python traceback; address the specific exception it names.","Re-download the model: delete the cached Kokoro model and voices under the HF cache dir and rerun (ensureModel/ensureVoices will re-fetch).","Install espeak-ng system-wide if the error mentions phonemization for a non-English lang.","For timeout (300s) on long text, synthesize shorter segments and concatenate.","Run the cached synth-v2.py manually with the same argv to reproduce the Python-side error outside the library."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  return await synthesize(text, out, { voice });\n} catch (err) {\n  if (err instanceof Error && err.message.startsWith('Speech synthesis failed')) {\n    // err.message includes the last 500 chars of the Python stderr — inspect it\n    console.error('TTS subprocess error:', err.message);\n    // retry with shorter text, a different voice, or after re-downloading the model\n  }\n  throw err;\n}","preventionTips":["Keep the Kokoro model/voices cache intact — re-run ensureModel/ensureVoices if downloads were interrupted.","Install espeak-ng system-wide before using non-English voices.","Chunk very long texts to stay well under the 300s subprocess timeout.","Capture and log the embedded stderr tail to diagnose the underlying Python exception quickly."],"tags":["tts","kokoro","subprocess","model","timeout","espeak"],"backgroundTag":null,"analyzedSha":"c2996c8626135db5253519359d8a063d3bafad8d","analyzedAt":"2026-08-12T22:18:56.877Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}