Hmbown/CodeWhale · error
invalid MCP OAuth callback port 0
Error message
invalid MCP OAuth callback port 0
What it means
When constructing the OAuth callback listener (oauth.rs:785), an explicit callback_port of Some(0) is rejected. Port 0 normally means 'ask the OS for an ephemeral port' in socket APIs, but here that behavior is expressed by passing None (the code binds {bind_host}:0 for that); an explicit Some(0) is therefore treated as a config mistake rather than honored.
Source
Thrown at crates/tui/src/mcp/oauth.rs:785
server_url: String,
}
impl OauthLoginFlow {
#[allow(clippy::too_many_arguments)]
async fn new(
server_name: &str,
server_url: &str,
http_headers: HashMap<String, String>,
env_headers: HashMap<String, String>,
scopes: &[String],
oauth_client_id: Option<&str>,
oauth_resource: Option<&str>,
callback_port: Option<u16>,
callback_url: Option<&str>,
) -> Result<Self> {
let bind_host = callback_bind_host(callback_url);
let bind_addr = match callback_port {
Some(0) => bail!("invalid MCP OAuth callback port 0"),
Some(port) => format!("{bind_host}:{port}"),
None => format!("{bind_host}:0"),
};
let listener = TcpListener::bind(&bind_addr)
.await
.map_err(|err| anyhow!(err))?;
let redirect_uri = resolve_redirect_uri(&listener, callback_url)?;
let callback_id = callback_id_from_server_url(server_url)?;
let redirect_uri = append_callback_id_to_redirect_uri(&redirect_uri, &callback_id)?;
let callback_path = callback_path_from_redirect_uri(&redirect_uri)?;
let (tx, rx) = oneshot::channel();
let guard = CallbackServerGuard {
accept_task: spawn_callback_server(listener, tx, callback_path),
};
let headers = build_default_headers(&http_headers, &env_headers)?;
let client = apply_default_headers(crate::tls::reqwest_client_builder(), &headers)View on GitHub (pinned to 0c42157ee5)
Solutions
- Omit the callback port entirely (None) — the client binds an ephemeral port and derives the redirect URI from it
- Or specify a concrete free port in 1024-65535 that matches the redirect URI registered with the OAuth provider
- Fix generators/scripts so 'automatic' is expressed by absence, not by 0
Example fix
# before /mcp login my-server --callback-port 0 # after /mcp login my-server
Defensive patterns
Strategy: validation
Validate before calling
if let Some(port) = callback_port {
ensure!(port != 0, "callback_port 0 is invalid; omit it for an ephemeral port");
} Prevention
- Represent 'automatic port' by omitting the option, not by 0
- Validate numeric UI/script options against 0 before passing them as ports
- Register the exact callback port (or a loopback redirect URI) with the OAuth provider beforehand
When it happens
Trigger: Invoking OAuth login with --callback-port 0, or a config/UI path that supplies callback_port: Some(0) to the callback server constructor.
Common situations: Users porting socket-code intuition ('pass 0 for a random port') to the OAuth callback config; automation scripts that default numeric options to 0; config generated by a tool that uses 0 as 'unset' sentinel.
Related errors
- OAuth login is only supported for URL-based MCP servers
- MCP server '{name}' already has bearer/static Authorization
- OAuth logout is only supported for URL-based MCP servers
- Browser login is only enabled for the canonical Codewhale ac
- MCP server '{server_name}' has no command configured
AI-assisted analysis of Hmbown/CodeWhale@0c42157ee5 (2026-08-20).
Data as JSON: /api/errors/72ece2bf9d133811.
Report an issue: GitHub.