{"record":{"id":"902a7a6a4c625fbb","repo":"zeroclaw-labs/zeroclaw","slug":"failed-to-open-url-with-default-browser-launcher","errorCode":null,"errorMessage":"Failed to open URL with default browser launcher: {primary_error}. Brave compatibility fallback also failed: {brave_error}","messagePattern":"Failed to open URL with default browser launcher: (.+?)\\. Brave compatibility fallback also failed: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/zeroclaw-tools/src/browser_open.rs","lineNumber":206,"sourceCode":"        let mut command = tokio::process::Command::new(\"open\");\n        command.arg(url);\n        let primary_error = match run_browser_launcher(command, \"open\").await {\n            Ok(()) => return Ok(()),\n            Err(error) => error,\n        };\n\n        // TODO(compat): remove Brave fallback after default-browser launch has been stable across macOS environments.\n        let mut brave_error = String::new();\n        for app in [\"Brave Browser\", \"Brave\"] {\n            let mut command = tokio::process::Command::new(\"open\");\n            command.arg(\"-a\").arg(app).arg(url);\n            match run_browser_launcher(command, &format!(\"open -a '{app}'\")).await {\n                Ok(()) => return Ok(()),\n                Err(error) => brave_error = error,\n            }\n        }\n\n        anyhow::bail!(\n            \"Failed to open URL with default browser launcher: {primary_error}. Brave compatibility fallback also failed: {brave_error}\"\n        );\n    }\n\n    #[cfg(target_os = \"linux\")]\n    {\n        let mut last_error = String::new();\n        for cmd in [\n            \"xdg-open\",\n            \"gio\",\n            \"sensible-browser\",\n            \"brave-browser\",\n            \"brave\",\n        ] {\n            let mut command = tokio::process::Command::new(cmd);\n            if cmd == \"gio\" {\n                command.arg(\"open\");\n            }","sourceCodeStart":188,"sourceCodeEnd":224,"githubUrl":"https://github.com/zeroclaw-labs/zeroclaw/blob/88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc/crates/zeroclaw-tools/src/browser_open.rs#L188-L224","documentation":"On macOS, browser_open first tries the system launcher `open <url>`; on failure it falls back to `open -a 'Brave Browser'` and `open -a 'Brave'`. If the primary launcher and both Brave fallbacks fail — non-zero exit, binary not runnable, or the 10-second launcher timeout — this combined error reports the primary and last fallback errors. Linux and Windows have parallel chains (xdg-open/gio/sensible-browser/brave on Linux).","triggerScenarios":"Calling browser_open on a headless macOS machine or over SSH with no GUI session (open exits non-zero); default browser misconfigured with Brave not installed; launcher binaries missing from PATH; a launcher hanging past the 10-second deadline.","commonSituations":"Agents running as daemons or in CI where no user GUI session exists; corporate machines where the default browser was removed; sandboxed environments without /usr/bin/open or xdg-open available.","solutions":["Verify a GUI session exists and `open https://example.com` (or xdg-open on Linux) works from the same user and terminal","Set a working default browser — the Brave fallback only helps if Brave is actually installed","On headless/CI hosts, disable browser_open and use scraping/automation tools instead; it fundamentally requires a desktop"],"exampleFix":null,"handlingStrategy":"fallback","validationCode":"// gate the tool on launcher availability before enabling it\n#[cfg(target_os = \"linux\")]\nlet can_launch = which::which(\"xdg-open\").is_some() || which::which(\"gio\").is_some();\n#[cfg(target_os = \"macos\")]\nlet can_launch = which::which(\"open\").is_some();\nif !can_launch {\n    return Err(\"no system browser launcher available; disable browser_open\".into());\n}","typeGuard":null,"tryCatchPattern":"match open_tool.execute(args).await {\n    Ok(res) if res.success => { /* opened */ }\n    Ok(res) => {\n        if res.error.as_deref().unwrap_or_default().contains(\"Failed to open URL with default browser launcher\") {\n            // fall back: log the URL for the user, or surface it in chat for manual opening\n        }\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Do not enable browser_open on headless hosts or CI runners","Verify `open <url>` / `xdg-open <url>` works from the same user session before deploying","Surface the URL to the user as a clickable fallback when launching fails","Set a valid default browser on machines where the tool runs"],"tags":["browser-open","launcher","system-browser","macos","environment"],"backgroundTag":"browser-launch-failed","analyzedSha":"88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc","analyzedAt":"2026-08-23T01:07:41.857Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}