zeroclaw-labs/zeroclaw · error
Edge TTS binary_path must be a bare command name without pat
Error message
Edge TTS binary_path must be a bare command name without path separators, got: {raw_path} What it means
EdgeTtsProvider::new rejects a binary_path containing '/' or '\\'. Edge TTS runs as a subprocess via tokio::process::Command::new(binary_path), so the config value is executed; the separator check is the first half of an allowlist security boundary that only permits bare command names resolved through PATH.
Source
Thrown at crates/zeroclaw-channels/src/tts.rs:646
}
std::thread::sleep(std::time::Duration::from_millis(50));
}
}
}
}
impl EdgeTtsProvider {
/// Allowed basenames for the Edge TTS binary.
const ALLOWED_BINARIES: &[&str] = &["edge-tts", "edge-playback"];
pub fn new(alias: &str, config: &TtsProviderConfig) -> Result<Self> {
let raw_path = config
.binary_path
.clone()
.filter(|p| !p.trim().is_empty())
.unwrap_or_else(|| "edge-tts".to_string());
if raw_path.contains('/') || raw_path.contains('\\') {
bail!(
"Edge TTS binary_path must be a bare command name without path separators, got: {raw_path}"
);
}
if !Self::ALLOWED_BINARIES.contains(&raw_path.as_str()) {
bail!(
"Edge TTS binary_path must be one of {:?}, got: {raw_path}",
Self::ALLOWED_BINARIES,
);
}
Ok(Self {
alias: alias.to_string(),
binary_path: raw_path,
#[cfg(test)]
binary_args: Vec::new(),
timeout: TTS_HTTP_TIMEOUT,
})
}
View on GitHub (pinned to 88bb9c8533)
Solutions
- Set binary_path to the bare name: binary_path = "edge-tts" (or remove the key; it is the default).
- Make the intended binary reachable via PATH (add the venv bin directory to PATH, or symlink it into a PATH directory like /usr/local/bin).
- Verify resolution with `command -v edge-tts` under the same user that runs the runtime.
Example fix
# before [providers.tts.edge.main] binary_path = "/opt/venvs/tts/bin/edge-tts" # after — bare name; ensure /opt/venvs/tts/bin is on PATH (or symlink into /usr/local/bin) [providers.tts.edge.main] binary_path = "edge-tts"
Defensive patterns
Strategy: validation
Validate before calling
// Validate the config value before constructing the provider.
fn is_bare_command_name(p: &str) -> bool {
!p.is_empty() && !p.contains('/') && !p.contains('\\')
}
if let Some(bin) = &edge_cfg.binary_path {
assert!(is_bare_command_name(bin), "binary_path must be a bare name; put the directory on PATH");
} Type guard
fn is_bare_command(p: &str) -> bool {
!p.contains('/') && !p.contains('\\')
} Prevention
- Treat binary_path as a name, not a path: default "edge-tts" needs no override in most setups.
- Make binary locations reachable via PATH (symlink into /usr/local/bin) instead of writing paths into config.
- Lint config files for '/' or '\\' in binary_path during CI.
When it happens
Trigger: Setting [providers.tts.edge.<alias>].binary_path to an absolute path (/usr/local/bin/edge-tts), a relative path (./edge-tts, bin/edge-tts), or any Windows path with a backslash. Empty or unset values are fine and default to "edge-tts".
Common situations: Admins harden the config by pinning an explicit binary location and are surprised the provider refuses it. CI environments installing edge-tts into a venv try to point at the venv's bin directory.
Understand the failure class
Background: Config validation failed: what "invalid value for {key}" and settings-rejection errors mean across 19 open-source libraries — this error's family across 19 libraries.
Related errors
- Edge TTS binary_path must be one of {:?}, got: {raw_path}
- security.nevis: {msg}
- Lark/Feishu marker target uses a disallowed scheme
- matrix: `homeserver` is required
- Cannot persist empty Telegram identity
AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23).
Data as JSON: /api/errors/3d0aae7066a8c5fe.
Report an issue: GitHub.