BigPizzaV3/CodexPlusPlus · error · anyhow::Error
CDP WebSocket URL must include an explicit port
Error message
CDP WebSocket URL must include an explicit port
What it means
connect_cdp_websocket (crates/codex-plus-core/src/bridge.rs:291) parses the ws URL and requires Url::port() to be Some before validating it against the debug port. For ws/wss schemes reqwest::Url has no well-known default port (only http/https/ftp do), so a URL like ws://127.0.0.1/devtools/browser/<id> without ':9222' yields port()==None and this error fires. It is a strict-input guard: the code refuses to guess a port.
Source
Thrown at crates/codex-plus-core/src/bridge.rs:291
}
pub fn reject_bridge_expression(request_id: &str, message: &str) -> anyhow::Result<String> {
Ok(format!(
"window.__codexSessionDeleteReject({}, {})",
serde_json::to_string(request_id)?,
serde_json::to_string(message)?,
))
}
async fn connect_cdp_websocket(
websocket_url: &str,
) -> anyhow::Result<
tokio_tungstenite::WebSocketStream<tokio_tungstenite::MaybeTlsStream<tokio::net::TcpStream>>,
> {
let parsed = reqwest::Url::parse(websocket_url).context("invalid CDP WebSocket URL")?;
let port = parsed
.port()
.ok_or_else(|| anyhow::anyhow!("CDP WebSocket URL must include an explicit port"))?;
crate::cdp::validate_cdp_websocket_url(websocket_url, port)?;
let (socket, _) = tokio::time::timeout(CDP_CONNECT_TIMEOUT, connect_async(websocket_url))
.await
.with_context(|| {
format!(
"timed out connecting CDP websocket after {}s",
CDP_CONNECT_TIMEOUT.as_secs()
)
})?
.context("failed to connect CDP websocket")?;
Ok(socket)
}
struct CdpSession<S> {
socket: S,
responses: HashMap<u64, Value>,
binding_calls: VecDeque<Value>,View on GitHub (pinned to 1f431ae49b)
Solutions
- Include the explicit port in the URL: ws://127.0.0.1:9222/devtools/browser/<id>
- Source the URL from the browser itself: GET http://127.0.0.1:<port>/json/version and use its webSocketDebuggerUrl verbatim (it always includes the port)
- If accepting user input, parse with Url and reject/repair port-less ws URLs before they reach the connector
Example fix
# before: no port — Url::port() returns None for ws scheme ws://127.0.0.1/devtools/browser/4f8a... # after: explicit port matching the remote debugging port ws://127.0.0.1:9222/devtools/browser/4f8a...
Defensive patterns
Strategy: validation
Validate before calling
// Validate shape before connecting
let u = reqwest::Url::parse(ws_url).context("invalid CDP WebSocket URL")?;
let port = u.port().context("CDP WebSocket URL must include an explicit port")?;
validate_cdp_websocket_url(ws_url, port)?; // also enforces ws/wss + loopback + port match Type guard
fn cdp_url_has_explicit_port(url: &str) -> bool {
reqwest::Url::parse(url).ok().and_then(|u| u.port()).is_some()
} Try / catch
match connect_cdp_websocket(ws_url).await {
Ok(socket) => Ok(socket),
Err(e) if e.to_string().contains("explicit port") => {
// repair by re-fetching the canonical URL from the browser
let fresh = fetch_websocket_debugger_url(port).await?;
connect_cdp_websocket(&fresh).await
}
Err(e) => Err(e),
} Prevention
- Always source ws URLs from /json/version's webSocketDebuggerUrl — it carries the port
- Never hand-assemble or sanitize CDP URLs by stripping components
- Validate scheme+host+port before any connect attempt
When it happens
Trigger: Passing a CDP WebSocket URL assembled by hand or trimmed of its port, e.g. ws://localhost/devtools/browser/abc, into any bridge helper that connects (screenshot, command send); URLs taken from the browser's /json/version endpoint always carry the explicit port and never trigger this.
Common situations: User config stores a sanitized URL without the port; code copies webSocketDebuggerUrl but strips ':9222' via a rewriting rule; a different default debug port (not 9222) makes hand-written URLs omit it; proxy/URL normalization middleware drops 'unnecessary' ports.
Related errors
- CDP WebSocket URL must include an explicit port
- CDP WebSocket URL has no host
- Page.captureScreenshot returned no image data
- browser WebSocket URL has no path
- selected CDP target has no websocket URL
AI-assisted analysis of BigPizzaV3/CodexPlusPlus@1f431ae49b (2026-08-16).
Data as JSON: /api/errors/8d0d4d5b509bc459.
Report an issue: GitHub.