{"record":{"id":"a5eeb77e878ce511","repo":"zeroclaw-labs/zeroclaw","slug":"unsupported-text-browser-browser-supported","errorCode":null,"errorMessage":"Unsupported text browser '{browser}'. Supported: {}","messagePattern":"Unsupported text browser '(.+?)'\\. Supported: (.+?)","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/zeroclaw-tools/src/text_browser.rs","lineNumber":146,"sourceCode":"            if let Ok(output) = tokio::process::Command::new(\"which\")\n                .arg(browser)\n                .output()\n                .await\n                && output.status.success()\n            {\n                return Some((*browser).to_string());\n            }\n        }\n        None\n    }\n\n    /// Resolve which browser to use: prefer configured, then auto-detect.\n    async fn resolve_browser(&self, requested: Option<&str>) -> anyhow::Result<String> {\n        // If the caller explicitly requested a browser via the tool parameter, use it.\n        if let Some(browser) = requested {\n            let browser = browser.trim().to_lowercase();\n            if !SUPPORTED_BROWSERS.contains(&browser.as_str()) {\n                anyhow::bail!(\n                    \"Unsupported text browser '{browser}'. Supported: {}\",\n                    SUPPORTED_BROWSERS.join(\", \")\n                );\n            }\n            // Verify it's installed\n            let installed = tokio::process::Command::new(\"which\")\n                .arg(&browser)\n                .output()\n                .await\n                .map(|o| o.status.success())\n                .unwrap_or(false);\n            if !installed {\n                anyhow::bail!(\"Requested text browser '{browser}' is not installed\");\n            }\n            return Ok(browser);\n        }\n\n        // If a preferred browser is set in config, try it first.","sourceCodeStart":128,"sourceCodeEnd":164,"githubUrl":"https://github.com/zeroclaw-labs/zeroclaw/blob/88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc/crates/zeroclaw-tools/src/text_browser.rs#L128-L164","documentation":"resolve_browser validates a caller-requested browser name against SUPPORTED_BROWSERS, the fixed list [\"lynx\",\"links\",\"w3m\"], after trimming and lowercasing it. A name outside that list — even a real browser like elinks, browsh, or firefox — bails with the supported set printed in the message.","triggerScenarios":"Tool parameter browser set to \"elinks\", \"browsh\", \"firefox\", \"chromium\", or any name not in the list; correct names still work in any case (\"Lynx\" passes after normalization).","commonSituations":"Users assuming any terminal or GUI browser works; elinks is the most common surprise since it is a popular lynx fork but absent from the list; configs copied from other tools that accept broader browser names.","solutions":["Use lynx, links, or w3m exactly (case-insensitive)","Omit the browser parameter entirely to let the tool auto-detect an installed one from the supported set","Install one of the three if none is present (see the 'not installed' error)"],"exampleFix":"// before\n{\"url\":\"https://example.com\",\"browser\":\"elinks\"}\n// after\n{\"url\":\"https://example.com\",\"browser\":\"lynx\"}","handlingStrategy":"validation","validationCode":"const SUPPORTED: &[&str] = &[\"lynx\",\"links\",\"w3m\"];\nlet b = requested.trim().to_lowercase();\nif !SUPPORTED.contains(&b.as_str()) { /* omit browser and let auto-detect run */ }","typeGuard":"fn is_supported_browser(b: &str) -> bool {\n    [\"lynx\",\"links\",\"w3m\"].contains(&b.trim().to_lowercase().as_str())\n}","tryCatchPattern":"Err(e) if e.to_string().starts_with(\"Unsupported text browser\") => {\n    // retry once with browser omitted so resolve_browser auto-detects\n}","preventionTips":["Restrict UI/config choices for the browser field to the supported three","Normalize user input (trim + lowercase) before validation","Prefer omitting the parameter and letting auto-detection choose"],"tags":["browser","enum","text-browser","validation"],"backgroundTag":"invalid-enum-value","analyzedSha":"88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc","analyzedAt":"2026-08-23T01:07:41.857Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}