zeroclaw-labs/zeroclaw · error · anyhow::Error
edge-tts failed (exit {}): {}
Error message
edge-tts failed (exit {}): {} What it means
The edge-tts subprocess exited within the timeout but with a non-zero status. synthesize drains the child's stderr concurrently (so the pipe cannot deadlock) and includes the exit code and stderr text in the error, so the message itself carries the CLI's own diagnosis.
Source
Thrown at crates/zeroclaw-channels/src/tts.rs:797
// deadline used above, so a child that ignores the kill
// cannot hold `synthesize` past the provider timeout; the
// artifact guard's `Drop` still owns the final reap.
let _ = tokio::time::timeout_at(deadline, child.kill()).await;
let _ = tokio::time::timeout_at(deadline, child.wait()).await;
return Err(err).context("Failed to wait for edge-tts subprocess");
}
Err(_elapsed) => {
reader.abort();
let _ = reader.await;
let _ = tokio::time::timeout_at(deadline, child.kill()).await;
let _ = tokio::time::timeout_at(deadline, child.wait()).await;
bail!("Edge TTS subprocess timed out");
}
}
};
if !status.success() {
bail!("edge-tts failed (exit {}): {}", status, stderr);
}
let bytes = tokio::fs::read(&output_file)
.await
.context("Failed to read edge-tts output file")?;
Ok(bytes)
}
fn supported_voices(&self) -> Vec<String> {
// Edge TTS has many voices; return common defaults.
[
"en-US-AriaNeural",
"en-US-GuyNeural",
"en-US-JennyNeural",
"en-GB-SoniaNeural",
]
.iter()View on GitHub (pinned to 88bb9c8533)
Solutions
- Read the stderr portion of the message; it is the CLI's own error text and pinpoints the cause.
- For voice errors, use a full neural voice name such as en-US-AriaNeural or en-GB-SoniaNeural.
- For HTTP/SSL/403 errors, upgrade: `pip install -U edge-tts`.
- Re-run the failing command manually with the same --text/--voice/--write-media arguments to confirm the fix.
Example fix
# before — short voice name, CLI exits non-zero [providers.tts.edge.main] voice = "Aria" # after — full Edge voice identifier [providers.tts.edge.main] voice = "en-US-AriaNeural"
Defensive patterns
Strategy: try-catch
Validate before calling
const KNOWN_EDGE_VOICES: &[&str] = &[
"en-US-AriaNeural", "en-US-GuyNeural", "en-US-JennyNeural", "en-GB-SoniaNeural",
];
// Fall back to a known-good full voice name before spawning the subprocess.
let voice = if KNOWN_EDGE_VOICES.contains(&voice) { voice } else { "en-US-AriaNeural" }; Type guard
fn is_full_edge_voice(v: &str) -> bool {
// full neural names end in "Neural" and carry a language prefix like en-US-
v.ends_with("Neural") && v.contains('-')
} Try / catch
match mgr.synthesize(text).await {
Ok(audio) => Ok(audio),
Err(err) if err.to_string().contains("edge-tts failed") => {
// stderr is embedded in the message; map common causes
let msg = err.to_string();
if msg.contains("Invalid voice") || msg.contains("voice") {
Err(err.context("use a full voice id like en-US-AriaNeural"))
} else if msg.contains("403") || msg.contains("SSL") || msg.contains("Errno") {
Err(err.context("edge-tts too old or offline: pip install -U edge-tts"))
} else {
Err(err)
}
}
Err(err) => Err(err),
} Prevention
- Always log the stderr tail embedded in the error — it is the CLI's own diagnosis and points at the fix.
- Use full neural voice identifiers (en-US-AriaNeural), not short forms.
- Schedule `pip install -U edge-tts` on your hosts; Microsoft endpoint changes break old releases with non-zero exits.
When it happens
Trigger: Unknown or retired voice name passed via --voice; edge-tts version too old for the current Microsoft endpoint (exits with an HTTP/SSL error on stderr); no internet (urllib/requests error on stderr); broken install (missing Python deps) producing an ImportError trace on stderr.
Common situations: Voice strings like "Aria" or "en-US-Aria" instead of the full "en-US-AriaNeural". Microsoft changes the endpoint auth roughly yearly and old pip releases die with a 403 on stderr; upgrading fixes it. Read the stderr tail first — it names the exact CLI failure.
Related errors
- Edge TTS subprocess timed out
- Edge TTS binary_path must be a bare command name without pat
- Edge TTS binary_path must be one of {:?}, got: {raw_path}
- lucid command failed: {stderr}
- Failed to speak: {}
AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23).
Data as JSON: /api/errors/bf98c47f8279a9ad.
Report an issue: GitHub.