{"record":{"id":"4404b40a0e74a04b","repo":"BigPizzaV3/CodexPlusPlus","slug":"no-injectable-codex-page-target-found","errorCode":null,"errorMessage":"No injectable Codex page target found","messagePattern":"No injectable Codex page target found","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/codex-plus-core/src/cdp.rs","lineNumber":270,"sourceCode":"    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\")\n}\n\nfn is_codex_app_page_target(target: &CdpTarget) -> bool {\n    let Ok(url) = reqwest::Url::parse(target.url.trim()) else {\n        return false;\n    };\n    url.scheme().eq_ignore_ascii_case(\"app\")\n        && url.host_str() == Some(\"-\")\n        && url.path().eq_ignore_ascii_case(\"/index.html\")\n}\n\npub fn is_injectable_page_target(target: &CdpTarget) -> bool {\n    target.target_type == \"page\"\n        && target\n            .web_socket_debugger_url\n            .as_deref()\n            .is_some_and(|url| !url.is_empty())\n}","sourceCodeStart":252,"sourceCodeEnd":288,"githubUrl":"https://github.com/BigPizzaV3/CodexPlusPlus/blob/f2074595a281bc057525c748175c8eb9805b0673/crates/codex-plus-core/src/cdp.rs#L252-L288","documentation":"pick_injectable_codex_page_target is the stricter picker: it walks four priority predicates (exact Codex app main target, primary Codex app target, ChatGPT desktop page, other supported Codex page) and requires the target to be injectable (type page plus ws URL). This error means injectable pages existed, but none looked like a Codex or ChatGPT surface — for example only an embedded browser page named codex or the standalone manager window, which are deliberately ignored.","triggerScenarios":"Calling pick_injectable_codex_page_target with a target list that contains no app-scheme Codex window and no ChatGPT desktop page: the user closed the Codex app, only the Codex++ manager window is open, or the open page matches the ignored embedded-browser/standalone-manager set.","commonSituations":"Codex desktop app not launched or stuck on a blank window; testing against about-blank or chrome pages; a Codex app update changed the target url or title shape so no predicate matches.","solutions":["Open and fully load the Codex app window (or a ChatGPT desktop page) before selecting a target","If Codex-specific matching is not required, fall back to pick_page_target which accepts any injectable page","Print the target list and compare each url and title against the predicates the crate matches on","After a Codex app update, adjust the matching predicates or file an issue with the target dump"],"exampleFix":"// before\nlet target = pick_injectable_codex_page_target(&targets)?;\n// after: fall back to any injectable page when no Codex surface is open\nlet target = pick_injectable_codex_page_target(&targets)\n    .or_else(|_| pick_page_target(&targets))?;","handlingStrategy":"fallback","validationCode":"let codex_open = targets.iter().any(|t| t.url.trim().to_ascii_lowercase().contains(\"codex\"));\nif !codex_open { /* launch or focus the Codex app before selecting */ }","typeGuard":"fn looks_like_codex_surface(target: &CdpTarget) -> bool {\n    let url = target.url.trim().to_ascii_lowercase();\n    url.starts_with(\"app://\") || url.contains(\"chatgpt\") || url.contains(\"codex\")\n}","tryCatchPattern":"let target = match pick_injectable_codex_page_target(&targets) {\n    Ok(t) => t,\n    Err(_) => pick_page_target(&targets)?, // lenient fallback: any injectable page\n};","preventionTips":["Confirm the Codex app window is open and loaded before selection","Log the full target list on failure to see which predicates missed","Treat the strict picker as best-effort and always keep the lenient fallback"],"tags":["cdp","codex","target-selection","app-not-open"],"backgroundTag":"cdp-codex-target-not-found","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"}