{"record":{"id":"2b032a093303f569","repo":"heygen-com/hyperframes","slug":"speech-was-generated-but-metadata-could-not-be-rea","errorCode":null,"errorMessage":"Speech was generated but metadata could not be read. Check the output file manually.","messagePattern":"Speech was generated but metadata could not be read\\. Check the output file manually\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"packages/cli/src/tts/synthesize.ts","lineNumber":199,"sourceCode":"    const jsonLine = lines[lines.length - 1] ?? \"\";\n    const result: {\n      outputPath: string;\n      sampleRate: number;\n      durationSeconds: number;\n      langApplied: boolean;\n    } = JSON.parse(jsonLine);\n\n    return {\n      outputPath: result.outputPath,\n      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":181,"sourceCodeEnd":212,"githubUrl":"https://github.com/heygen-com/hyperframes/blob/c2996c8626135db5253519359d8a063d3bafad8d/packages/cli/src/tts/synthesize.ts#L181-L212","documentation":"Synthesis actually succeeded — the WAV exists at outputPath — but JSON.parse on the last line of the Python stdout threw a SyntaxError. The inline script prints a JSON metadata object as its final line; if Python emitted a warning, traceback fragment, or print AFTER that line (or if the JSON was malformed), parsing fails. The library deliberately surfaces a clearer message rather than re-throwing the raw SyntaxError or fabricating metadata.","triggerScenarios":"A Python warning (e.g. from torch/onnxruntime) printed to stdout AFTER the JSON line; the script printed a deprecation warning without a trailing newline ordering; a newer kokoro-onnx prints a progress/info line after the JSON; multi-line stdout where the 'last line' heuristic grabs a partial JSON fragment.","commonSituations":"User upgraded kokoro-onnx and the new version logs to stdout; PYTHONUNBUFFERED or a logging config that emits to stdout; a NumPy/torch ABI warning that prints at import time after the metadata print; stderr/stdout interleaving under some CI log capturers.","solutions":["The audio file was created — use it directly; the metadata (sampleRate, durationSeconds) can be re-derived from the WAV header if needed.","Set PYTHONWARNINGS=ignore to suppress warnings that may print to stdout after the JSON line.","Inspect the cached synth-v2.py: confirm the json.dumps print is the absolute last statement with no trailing code.","Capture and read the Python stdout yourself to see what came after the JSON line and report the noise source."],"exampleFix":null,"handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  return await synthesize(text, out, { voice });\n} catch (err) {\n  if (err instanceof Error && /metadata could not be read/.test(err.message) && existsSync(out)) {\n    // synthesis succeeded — derive metadata from the WAV header instead of failing\n    return { outputPath: out, sampleRate: readWavSampleRate(out), durationSeconds: readWavDuration(out), langApplied: false };\n  }\n  throw err;\n}","preventionTips":["Set PYTHONWARNINGS=ignore to keep warnings off stdout where they can follow the JSON line.","If you control the pipeline, treat the existing WAV as success even when metadata is unreadable.","Pin kokoro-onnx to a version known to print only the JSON line to stdout."],"tags":["tts","metadata","json","subprocess","stdout","kokoro"],"backgroundTag":null,"analyzedSha":"c2996c8626135db5253519359d8a063d3bafad8d","analyzedAt":"2026-08-12T22:18:56.877Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}