Hmbown/CodeWhale · warning
failed to launch browser command
Error message
failed to launch browser command: {err} What it means
spawn_external_url_command builds an OS command (e.g. xdg-open/open/browser binary) to open a URL and calls .spawn(). When the OS fails to start the process — binary not found, permission denied, exec format error — the io::Error is wrapped into this anyhow error. The TUI then reports that the URL could not be opened in a browser.
Solutions
- Install an opener for your platform (xdg-open on Linux via xdg-utils, `open` exists on macOS) or install a browser.
- Check/fix the BROWSER environment variable so it names an existing executable.
- Verify the command exists: run `which xdg-open` (or the configured binary) in the same environment; fix PATH if missing.
- In code, fall back to printing the URL so the user can open it manually when spawn fails.
Defensive patterns
Strategy: fallback
Validate before calling
let cmd = opener_command(); // e.g. xdg-open / open
if which::which(&cmd).is_err() {
eprintln!("No browser opener found; open this URL manually: {url}");
return Ok(());
} Type guard
fn opener_available(cmd: &str) -> bool { std::process::Command::new(cmd).arg("--version").output().is_ok() } Try / catch
match spawn_external_url_command(&cmd, &url) {
Ok(()) => {},
Err(err) => {
log::warn!("{err}");
print!("Open manually: {url}"); // graceful fallback
}
} Prevention
- Ensure xdg-utils (Linux) is installed in containers/servers, or set BROWSER to a real executable.
- Check `which xdg-open` / `$BROWSER` in the same environment the TUI runs in.
- Keep a fallback that echoes the URL so users on headless machines are never stuck.
When it happens
Trigger: Calling spawn_external_url_command (via the URL opener path, e.g. from a test or the external_url_launcher) when the configured browser/open command does not exist on PATH, is not executable, or the OS refuses to fork/exec.
Common situations: Minimal Docker/container images or headless servers with no xdg-open, sensible-browser, or open installed; a BROWSER env var pointing at a nonexistent binary; PATH not set in the launch environment; macOS on Linux or vice versa.
Related errors
- browser opening is unsupported on this platform
- failed to launch browser command
- lane child stderr was not piped
- lane child stdout was not piped
- validated Fleet tool authority envelope must serialize
AI-assisted analysis of Hmbown/CodeWhale@433685b202 (2026-09-15).
Data as JSON: /api/errors/38873836223f924a.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/tui/ui.rs:940
pub(crate) mod frame;
mod overlays;
mod provider_routes;
mod session_state;
pub(crate) use frame::*;
pub(crate) use overlays::*;
pub(crate) use provider_routes::*;
pub(crate) use session_state::*;
#[cfg(test)]
fn spawn_external_url_command(mut command: Command) -> Result<()> {
command
.stdin(Stdio::null())
.stdout(Stdio::null())
.stderr(Stdio::null())
.spawn()
.map(|_| ())
.map_err(|err| anyhow::anyhow!("failed to launch browser command: {err}"))
}
async fn execute_command_input(
terminal: &mut AppTerminal,
app: &mut App,
engine_handle: &mut EngineHandle,
task_manager: &SharedTaskManager,
config: &mut Config,
input: &str,
) -> Result<bool> {
let _ = app.note_manual_command_for_tip(input);
if let Some(parsed_index) = parse_queue_send_command(input) {
match parsed_index {
Ok(index) => {
send_queued_message_at_index_now(app, config, engine_handle, index).await?;
}
Err(message) => {
app.status_message = Some(message);View on GitHub (pinned to 433685b202)