chenhg5/cc-connect · error
pico2wave: read output file: %w
Error message
pico2wave: read output file: %w
What it means
After pico2wave exits successfully, PicoTTS.Synthesize reads back the WAV file it was told to write (os.ReadFile on the temp path); this error wraps a failure to read that file. Since CreateTemp succeeded moments earlier, this usually means pico2wave never actually wrote the file (exit 0 without producing output), the file was removed in between, or namespace isolation (e.g. systemd PrivateTmp) gave the child process a different view of the temp directory.
Source
Thrown at core/tts.go:646
// --lang: language code (zh-CN for Chinese, en-US for English)
// --wave: output WAV file path
args := []string{
"--lang=" + voice,
"--wave=" + tmpPath,
text,
}
// Execute pico2wave command
cmd := exec.CommandContext(ctx, p.Path, args...)
output, err := cmd.CombinedOutput()
if err != nil {
return nil, "", fmt.Errorf("pico2wave: voice=%s text=%q: %w, output: %s", voice, text, err, string(output))
}
// Read the generated WAV file
audioData, err := os.ReadFile(tmpPath)
if err != nil {
return nil, "", fmt.Errorf("pico2wave: read output file: %w", err)
}
if len(audioData) == 0 {
return nil, "", fmt.Errorf("pico2wave: produced empty audio file")
}
return audioData, "wav", nil
}
// ──────────────────────────────────────────────────────────────
// EdgeTTS — Microsoft Edge TTS (free, high quality, requires network)
// ──────────────────────────────────────────────────────────────
// EdgeTTS implements TextToSpeech using Microsoft Edge's free TTS API.
// This uses the edge-tts CLI command under the hood.
type EdgeTTS struct {
Path string // path to edge-tts executable (empty = "edge-tts")
Voice string // default voice (e.g. "zh-CN-XiaoxiaoNeural")View on GitHub (pinned to 4000b2338a)
Solutions
- Check file existence right before reading (os.Stat) and report the temp path plus pico2wave's combined output in the error for diagnosis.
- Guard empty text before invoking pico2wave: return an error when strings.TrimSpace(text) == "".
- Re-run the exact command manually to confirm pico2wave creates the file: pico2wave --lang=en-US --wave=/tmp/t.wav "hello".
- Check for PrivateTmp/namespace isolation (systemd, containers) making the child's tmp differ; use a shared writable directory.
- Include tmpPath in the error message to distinguish 'file missing' from 'permission/read failure'.
Example fix
// before
audioData, err := os.ReadFile(tmpPath)
if err != nil {
return nil, "", fmt.Errorf("pico2wave: read output file: %w", err)
}
// after
if _, statErr := os.Stat(tmpPath); statErr != nil {
return nil, "", fmt.Errorf("pico2wave: wrote no output file %s (exit 0, output: %s): %w", tmpPath, string(output), statErr)
}
audioData, err := os.ReadFile(tmpPath)
if err != nil {
return nil, "", fmt.Errorf("pico2wave: read output file %s: %w", tmpPath, err)
} Defensive patterns
Strategy: try-catch
Validate before calling
// Go: guard empty text — the main cause of silent no-output runs
if strings.TrimSpace(text) == "" {
return errors.New("pico2wave: empty text")
} Try / catch
audio, format, err := pico.Synthesize(ctx, text, opts)
if err != nil {
if strings.Contains(err.Error(), "read output file") {
// pico2wave exited 0 but wrote nothing — treat as engine failure;
// check PrivateTmp/tmp isolation, then retry with another engine
return espeak.Synthesize(ctx, text, opts)
}
return err
} Prevention
- Reject empty/whitespace-only text before invoking the engine.
- Test pico2wave WAV output manually in the target deployment to rule out PrivateTmp/namespace isolation.
- Avoid aggressive /tmp cleaners on hosts running local TTS.
- Check that the produced WAV is non-empty; a read error usually means no file was written at all.
When it happens
Trigger: Calling Synthesize via PicoTTS when the pico2wave process returns exit code 0 but does not create/write --wave=<tmpPath> (e.g. empty or no-op text); the temp file is deleted between creation and read; the deferred os.Remove of an overlapping call removes it; or the child runs in a private tmp namespace.
Common situations: pico2wave builds that report success while failing to synthesize (empty text producing no output); systemd PrivateTmp or container namespace isolation separating the child's /tmp from the parent's; aggressive /tmp cleaners; text treated as a no-op by the engine.
Understand the failure class
Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.
Related errors
- pico2wave: create temp file: %w
- edge-tts: read output file: %w
- read existing Agy hooks %s: %w
- pico2wave: voice=%s text=%q: %w, output: %s
- pico2wave: produced empty audio file
AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06).
Data as JSON: /api/errors/73d5209fe2e5baee.
Report an issue: GitHub.