{"record":{"id":"55ceaa939c61c8d7","repo":"BigPizzaV3/CodexPlusPlus","slug":"no-injectable-page-target-found","errorCode":null,"errorMessage":"No injectable page target found","messagePattern":"No injectable page target found","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/codex-plus-core/src/cdp.rs","lineNumber":252,"sourceCode":"}\n\npub fn pick_page_target(targets: &[CdpTarget]) -> anyhow::Result<CdpTarget> {\n    let mut first_page = None;\n    for target in targets\n        .iter()\n        .filter(|target| is_injectable_page_target(target))\n    {\n        first_page.get_or_insert(target);\n        if is_primary_codex_page_target(target) {\n            return Ok(target.clone());\n        }\n    }\n\n    if let Some(target) = first_page {\n        return Ok(target.clone());\n    }\n\n    bail!(\"No injectable page target found\")\n}\n\npub fn pick_injectable_codex_page_target(targets: &[CdpTarget]) -> anyhow::Result<CdpTarget> {\n    let priorities: [fn(&CdpTarget) -> bool; 4] = [\n        is_exact_codex_app_main_target,\n        is_primary_codex_app_target,\n        is_chatgpt_desktop_page_target,\n        is_supported_codex_page_target,\n    ];\n    for matches_priority in priorities {\n        if let Some(target) = targets\n            .iter()\n            .find(|target| is_injectable_page_target(target) && matches_priority(target))\n        {\n            return Ok(target.clone());\n        }\n    }\n    bail!(\"No injectable Codex page target found\")","sourceCodeStart":234,"sourceCodeEnd":270,"githubUrl":"https://github.com/BigPizzaV3/CodexPlusPlus/blob/f2074595a281bc057525c748175c8eb9805b0673/crates/codex-plus-core/src/cdp.rs#L234-L270","documentation":"pick_page_target selects a Chrome tab to inject into from a /json target list. A target is injectable only when target_type equals page and web_socket_debugger_url is present and non-empty; the picker then prefers the primary Codex page and otherwise falls back to the first injectable page. This error means not a single target in the list was injectable: there were no page-type targets, or every page lacked a WebSocket debugger URL.","triggerScenarios":"Passing a CdpTarget list where all targets are service_worker, background_page, iframe or other non-page types; querying /json when every tab is closed; the browser was launched with --remote-debugging-pipe instead of a port so pages expose no webSocketDebuggerUrl.","commonSituations":"Headless Chrome started with pipe-based debugging; all tabs closed by selection time; target list fetched from /json/version or a non-Chromium endpoint that returns no targets array; DevTools already holding the only debug session on the page.","solutions":["Open or keep at least one regular tab in the browser being debugged","Relaunch the browser with --remote-debugging-port=PORT (not --remote-debugging-pipe) so pages expose webSocketDebuggerUrl","Verify the list came from http://127.0.0.1:PORT/json and includes targets of type page","Close other DevTools clients holding sessions on the pages, then re-query"],"exampleFix":"// before: selection on a possibly empty list\nlet target = pick_page_target(&targets)?;\n// after: ensure an injectable page exists first\nensure_browser_has_open_page(&client, debug_port).await?;\nlet targets = query_targets_url(&client, &list_url, debug_port).await?;\nlet target = pick_page_target(&targets)?;","handlingStrategy":"validation","validationCode":"let injectable = targets.iter().any(|t| t.target_type == \"page\" && t.web_socket_debugger_url.as_deref().is_some_and(|u| !u.is_empty()));\nif !injectable {\n    // open a tab or relaunch with --remote-debugging-port, then re-query\n}","typeGuard":"fn has_injectable_page_target(targets: &[CdpTarget]) -> bool {\n    targets.iter().any(|t| t.target_type == \"page\" && t.web_socket_debugger_url.as_deref().is_some_and(|u| !u.is_empty()))\n}","tryCatchPattern":"if let Err(e) = pick_page_target(&targets) {\n    if e.to_string().contains(\"No injectable page target\") {\n        open_or_relaunch_browser().await?;\n        let targets = requery_targets(debug_port).await?;\n        return pick_page_target(&targets);\n    }\n    return Err(e);\n}","preventionTips":["Check the target list for a page entry before picking","Prefer --remote-debugging-port over pipe mode","Keep at least one ordinary tab open while injecting"],"tags":["cdp","target-selection","chrome-devtools","no-injectable-page"],"backgroundTag":"cdp-no-page-targets","analyzedSha":"f2074595a281bc057525c748175c8eb9805b0673","analyzedAt":"2026-08-23T12:52:24.489Z","contentChangedAt":"2026-08-23T12:52:24.489Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}