{"record":{"id":"690a9cb76806bed1","repo":"BigPizzaV3/CodexPlusPlus","slug":"cdp-websocket-url-must-include-an-explicit-port-690a9c","errorCode":null,"errorMessage":"CDP WebSocket URL must include an explicit port","messagePattern":"CDP WebSocket URL must include an explicit port","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/codex-plus-core/src/cdp.rs","lineNumber":229,"sourceCode":"pub fn validate_cdp_websocket_url(url: &str, expected_port: u16) -> anyhow::Result<()> {\n    let parsed = reqwest::Url::parse(url).context(\"invalid CDP WebSocket URL\")?;\n    if !matches!(parsed.scheme(), \"ws\" | \"wss\") {\n        bail!(\"CDP WebSocket URL must use ws or wss\");\n    }\n    let host = parsed\n        .host_str()\n        .ok_or_else(|| anyhow::anyhow!(\"CDP WebSocket URL has no host\"))?;\n    let address = host\n        .trim_start_matches('[')\n        .trim_end_matches(']')\n        .parse::<IpAddr>()\n        .with_context(|| \"CDP WebSocket host must be a loopback IP address\")?;\n    if !address.is_loopback() {\n        bail!(\"CDP WebSocket host must be loopback\");\n    }\n    let port = parsed\n        .port()\n        .ok_or_else(|| anyhow::anyhow!(\"CDP WebSocket URL must include an explicit port\"))?;\n    if port != expected_port {\n        bail!(\"CDP WebSocket port {port} does not match debug port {expected_port}\");\n    }\n    Ok(())\n}\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","sourceCodeStart":211,"sourceCodeEnd":247,"githubUrl":"https://github.com/BigPizzaV3/CodexPlusPlus/blob/b1ed92e5e4a2d74095d4b8db5af43cef7acba9c6/crates/codex-plus-core/src/cdp.rs#L211-L247","documentation":"In the same `validate_cdp_websocket_url` guard, after scheme and loopback-host checks the URL must carry an explicit port, which is compared with the expected Chrome remote-debugging port. `Url::port()` returns None when the port is omitted (or is the scheme default), so this error fires for portless ws:// URLs. It guarantees the caller is talking to the exact debug endpoint.","triggerScenarios":"Calling `validate_cdp_websocket_url` with `ws://127.0.0.1/devtools/...` (no `:port`), or a URL whose port was normalized away (e.g. `:443` on wss), via any of its callers (`query_targets_url`, `browser_identity`, tests, bridge connect).","commonSituations":"Constructing the debugger URL from a template without substituting the port, copying an URL and losing `:9222`, or normalization code that drops default ports.","solutions":["Append the remote-debugging port explicitly: ws://127.0.0.1:9222/devtools/...","Take the URL verbatim from /json/version's webSocketDebuggerUrl, which always includes the port","Pass the same port value you launched Chrome with (`--remote-debugging-port`) as `expected_port`","If using a default scheme port, serialize it explicitly since Url::port() collapses it to None"],"exampleFix":"// before\nlet url = format!(\"ws://{host}/devtools/page/{target}\");\n// after\nlet url = format!(\"ws://{host}:{port}/devtools/page/{target}\");","handlingStrategy":"validation","validationCode":"let u = reqwest::Url::parse(&url)?;\nif u.port().is_none() { bail!(\"CDP URL needs explicit port: {url}\"); }\nif u.port() != Some(expected_port) { bail!(\"port mismatch\"); }","typeGuard":null,"tryCatchPattern":"match validate_cdp_websocket_url(&url, debug_port) {\n    Err(e) if e.to_string().contains(\"explicit port\") => bail!(\"bad CDP URL, expected :{debug_port}\"),\n    Err(e) => return Err(e),\n    Ok(()) => proceed(),\n}","preventionTips":["Format the port into every ws:// URL you construct","Launch Chrome with --remote-debugging-port and reuse that exact port","Avoid URL normalization that drops default ports before validation"],"tags":["cdp","url-validation","websocket","port"],"backgroundTag":"invalid-url-format","analyzedSha":"b1ed92e5e4a2d74095d4b8db5af43cef7acba9c6","analyzedAt":"2026-09-19T23:35:21.129Z","contentChangedAt":"2026-09-19T23:35:21.129Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}