BigPizzaV3/CodexPlusPlus · error

selected CDP target has no websocket URL

Error message

selected CDP target has no websocket URL

What it means

After listing CDP targets and picking an injectable Codex page target, the launcher reads target.web_socket_debugger_url to attach a WebSocket for script injection. This error is thrown with ok_or_else when that optional field is None — the selected target exists but the DevTools handshake URL the debugger would connect to is absent, so injection cannot proceed.

Solutions

  1. Re-list CDP targets and retry until the chosen page exposes webSocketDebuggerUrl (page fully loaded)
  2. Tighten pick_injectable_codex_page_target to only select targets guaranteed to have a WS URL
  3. Confirm the browser version supports webSocketDebuggerUrl on /json targets
  4. Navigate the Codex page manually first, then rerun injection
Defensive patterns

Strategy: validation

Validate before calling

fn target_has_ws_url(t: &codex_plus_core::cdp::Target) -> bool {
    t.web_socket_debugger_url.as_deref().map_or(false, |u| u.starts_with("ws"))
}
// 注入前:只挑选带 WS URL 的可注入 target
let target = targets.iter().find(|t| target_has_ws_url(t));

Type guard

fn has_websocket_url(target: &Target) -> Option<&str> {
    target.web_socket_debugger_url.as_deref().filter(|u| !u.is_empty())
}

Prevention

When it happens

Trigger: codex_plus_core::cdp::pick_injectable_codex_page_target returned a target whose web_socket_debugger_url field is None — e.g. the /json target list contained an entry without a webSocketDebuggerUrl (about:blank, still-loading page, or a non-page target that slipped through the picker).

Common situations: Attaching to a browser page before it finished loading (DevTools WS URL not yet assigned), targeting browsers that omit webSocketDebuggerUrl for certain targets, or a picker filter that matches more target kinds than the CDP implementation supports.

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


AI-assisted analysis of BigPizzaV3/CodexPlusPlus@b1ed92e5e4 (2026-09-19). Data as JSON: /api/errors/13e4e1ef1582dde6. Report an issue: GitHub.

Appendix: source

Thrown at apps/codex-plus-launcher/src/main.rs:1049

    request: &codex_plus_core::remote_control_recovery::PendingRemoteControlRecovery,
) -> bool {
    settings.active_relay_id == request.profile_id
        && settings.active_relay_session_provider()
            == codex_plus_core::settings::RelaySessionProvider::Openai
}

async fn try_inject_with_context(
    debug_port: u16,
    helper_port: u16,
    ctx: BridgeContext,
    runtime: Arc<LauncherRuntimeService>,
) -> anyhow::Result<()> {
    let targets = codex_plus_core::cdp::list_targets(debug_port).await?;
    let target = codex_plus_core::cdp::pick_injectable_codex_page_target(&targets)?;
    let websocket_url = target
        .web_socket_debugger_url
        .as_deref()
        .ok_or_else(|| anyhow::anyhow!("selected CDP target has no websocket URL"))?;
    runtime.set_websocket_url(websocket_url);
    let settings = codex_plus_core::settings::SettingsStore::default()
        .load()
        .unwrap_or_default();
    let script = codex_plus_core::assets::injection_script_with_settings(helper_port, &settings);
    let user_bundle = runtime
        .user_scripts
        .build_enabled_bundle()
        .unwrap_or_default();
    let new_document_scripts = if user_bundle.is_empty() {
        vec![script]
    } else {
        vec![script, user_bundle]
    };
    codex_plus_core::bridge::install_bridge(
        websocket_url,
        codex_plus_core::bridge::BRIDGE_BINDING_NAME,
        Arc::new(move |path, payload| {

View on GitHub (pinned to b1ed92e5e4)