{"record":{"id":"1f9e10c86e5beaa9","repo":"RightNow-AI/openfang","slug":"click-failed","errorCode":null,"errorMessage":"Click failed","messagePattern":"Click failed","errorType":"http","errorClass":"BrowserResponse","httpStatus":null,"severity":"error","filePath":"crates/openfang-runtime/src/browser.rs","lineNumber":464,"sourceCode":"        for (const e of all) {{\n            if (e.textContent.trim().toLowerCase().includes(lower)) {{ el = e; break; }}\n        }}\n    }}\n    if (!el) return JSON.stringify({{success: false, error: 'Element not found: ' + sel}});\n    el.scrollIntoView({{block: 'center'}});\n    el.click();\n    return JSON.stringify({{success: true, tag: el.tagName, text: el.textContent.substring(0, 100).trim()}});\n}})()\"#\n        );\n\n        match self.cdp.run_js(&js).await {\n            Ok(val) => {\n                let parsed: serde_json::Value = val\n                    .as_str()\n                    .and_then(|s| serde_json::from_str(s).ok())\n                    .unwrap_or(val);\n                if parsed[\"success\"].as_bool() == Some(false) {\n                    return BrowserResponse::err(\n                        parsed[\"error\"]\n                            .as_str()\n                            .unwrap_or(\"Click failed\")\n                            .to_string(),\n                    );\n                }\n                // Wait briefly for any navigation triggered by click\n                tokio::time::sleep(Duration::from_millis(500)).await;\n                self.wait_for_load().await;\n                match self.page_info().await {\n                    Ok(info) => BrowserResponse::ok(info),\n                    Err(_) => BrowserResponse::ok(parsed),\n                }\n            }\n            Err(e) => BrowserResponse::err(format!(\"Click failed: {e}\")),\n        }\n    }\n","sourceCodeStart":446,"sourceCodeEnd":482,"githubUrl":"https://github.com/RightNow-AI/openfang/blob/acf2587e46be174c10200489c9a2d23a39a98aeb/crates/openfang-runtime/src/browser.rs#L446-L482","documentation":"cmd_click evaluates a JS snippet via CDP that clicks the element matching a selector and returns {success, error} JSON. When the script reports success=false, this fallback message 'Click failed' is used if the script did not include an 'error' string — i.e. the click script itself determined the click could not be performed (element not found, not clickable).","triggerScenarios":"Running the click JS over CDP returns a value whose parsed[\"success\"] is false and parsed[\"error\"] is missing or not a string — e.g. the injected script failed to find the selector and returned success:false without a message.","commonSituations":"Selector typo or element rendered client-side after the click attempt; element inside an iframe the script doesn't reach; stale selector after a re-render.","solutions":["Verify the selector matches exactly one visible element (test it in the browser console with document.querySelector).","Use cmd_wait on the selector before clicking to ensure it exists in the DOM.","Inspect the parsed error payload — the script usually returns a more specific 'error' field than this fallback.","For shadow DOM or iframes, use a selector strategy that penetrates them or switch frames first."],"exampleFix":"// before\nlet _ = browser.execute(\"click\", selector).await?;\n// after\nbrowser.execute(\"wait\", &format!(\"{selector}|5000\")).await?;\nlet resp = browser.execute(\"click\", selector).await?;\nif !resp.success { return Err(anyhow!(resp.error)); }","handlingStrategy":"validation","validationCode":"// Ensure the element exists before clicking:\nlet wait = browser.execute(\"wait\", &format!(\"{selector}|5000\")).await?;\nif !wait.success { return Err(anyhow!(\"element not present: {selector}\")); }","typeGuard":"fn click_failed_no_reason(resp: &BrowserResponse) -> bool {\n    !resp.success && resp.error == \"Click failed\"\n}","tryCatchPattern":"// Rust\nlet resp = browser.execute(\"click\", selector).await?;\nif !resp.success {\n    if resp.error == \"Click failed\" {\n        // no script-side reason — most likely selector miss; wait and retry once\n        browser.execute(\"wait\", &format!(\"{selector}|3000\")).await?;\n        return browser.execute(\"click\", selector).await.map_err(Into::into);\n    }\n    return Err(anyhow!(resp.error));\n}\nOk(resp)","preventionTips":["Always wait for the selector before clicking.","Validate selectors in devtools/console first.","Prefer stable data-* attributes over generated class names.","Handle iframes/shadow DOM explicitly before clicking inside them."],"tags":["selector","dom","browser-automation"],"backgroundTag":"element-not-found","analyzedSha":"acf2587e46be174c10200489c9a2d23a39a98aeb","analyzedAt":"2026-09-02T22:42:28.464Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-10T02:17:09.455Z"}