{"record":{"id":"02df098128cefc16","repo":"chenhg5/cc-connect","slug":"edge-tts-read-output-file-w","errorCode":null,"errorMessage":"edge-tts: read output file: %w","messagePattern":"edge-tts: read output file: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/tts.go","lineNumber":715,"sourceCode":"\t\t\"--voice\", voice,\n\t\t\"--text\", text,\n\t\t\"--write-media\", tmpPath,\n\t}\n\n\tpath := e.Path\n\tif path == \"\" {\n\t\tpath = \"edge-tts\"\n\t}\n\tcmd := exec.CommandContext(ctx, path, args...)\n\toutput, err := cmd.CombinedOutput()\n\tif err != nil {\n\t\treturn nil, \"\", fmt.Errorf(\"edge-tts: voice=%s text=%q: %w, output: %s\", voice, text, err, string(output))\n\t}\n\n\t// Read the generated MP3 file\n\taudioData, err := os.ReadFile(tmpPath)\n\tif err != nil {\n\t\treturn nil, \"\", fmt.Errorf(\"edge-tts: read output file: %w\", err)\n\t}\n\n\tif len(audioData) == 0 {\n\t\treturn nil, \"\", fmt.Errorf(\"edge-tts: produced empty audio file\")\n\t}\n\n\treturn audioData, \"mp3\", nil\n}\n","sourceCodeStart":697,"sourceCodeEnd":724,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/core/tts.go#L697-L724","documentation":"EdgeTTS.Synthesize (core/tts.go:715) reads back the MP3 temp file that the edge-tts CLI was told to write via --write-media. This error wraps os.ReadFile failure after the CLI exited 0, meaning the output file vanished, was never created at the expected path, or is unreadable. It indicates a mismatch between where the CLI wrote (or failed to write) and where the library reads.","triggerScenarios":"Calling EdgeTTS.Synthesize when os.ReadFile(tmpPath) fails after successful CLI exit — the temp file was deleted between creation and read (e.g. aggressive /tmp cleaner or another process using the same path), edge-tts exited 0 without writing --write-media output, or permission changes on the temp file made it unreadable.","commonSituations":"Environments running systemd-tmpfiles or security cleaners that race with the synthesis, custom e.Path wrappers that succeed without honoring --write-media, or odd mounts (FIFO/named volumes) where file creation semantics differ.","solutions":["Check nothing is purging /tmp during synthesis (systemd-tmpfiles age settings, tmpwatch, custom cleanup jobs)","Run the exact command manually (`edge-tts --voice <v> --text 'test' --write-media /tmp/x.mp3`) to confirm it actually creates the file","Upgrade edge-tts; some versions exit 0 on failure without writing the output file","Check file permissions and that TMPDIR is on a normal local filesystem, not a special mount"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"if _, err := exec.LookPath(\"edge-tts\"); err != nil {\n    return errors.New(\"edge-tts CLI not installed\")\n}\n// ensure no tmp reaper races the synthesis\nout, err := exec.Command(\"edge-tts\", \"--voice\", voice, \"--text\", \"ping\", \"--write-media\", \"/tmp/tts_check.mp3\").Output()\n_ = out; _ = err","typeGuard":null,"tryCatchPattern":"audio, format, err := edge.Synthesize(ctx, text, opts)\nif err != nil {\n    if strings.Contains(err.Error(), \"read output file\") {\n        slog.Warn(\"edge-tts output missing/unreadable; retrying once\")\n        audio, format, err = edge.Synthesize(ctx, text, opts)\n    }\n    if err != nil {\n        return err\n    }\n}","preventionTips":["Disable or tune tmpfile cleaners (systemd-tmpfiles age, tmpwatch) so they don't delete files mid-synthesis","Use a dedicated writable temp directory for TTS instead of shared /tmp","Confirm the edge-tts version honors --write-media and exits non-zero on failure","Run a startup self-test that verifies a full synthesize-write-read roundtrip"],"tags":["filesystem","tts","edge-tts","temp-file","file-read"],"backgroundTag":"file-read-failed","analyzedSha":"4000b2338aa6e850c99df54f8b0ed6ed7460b401","analyzedAt":"2026-09-06T11:45:09.575Z","contentChangedAt":"2026-09-06T11:45:09.575Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}