{"record":{"id":"08ebf11f60e136a7","repo":"Kuberwastaken/claurst","slug":"failed-to-parse-redirect-uri","errorCode":null,"errorMessage":"Failed to parse redirect URI '{}': {}","messagePattern":"Failed to parse redirect URI '(.+?)': (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"src-rust/crates/mcp/src/oauth.rs","lineNumber":218,"sourceCode":"        &metadata.authorization_endpoint,\n        &redirect_uri,\n        &verifier,\n    );\n\n    Ok(McpAuthSession {\n        server_name: server_name.to_string(),\n        auth_url,\n        redirect_uri,\n        verifier,\n        metadata,\n    })\n}\n\nasync fn bind_callback_listener(\n    redirect_uri: &str,\n) -> anyhow::Result<(TcpListener, String, String)> {\n    let redirect_url = url::Url::parse(redirect_uri)\n        .map_err(|e| anyhow::anyhow!(\"Failed to parse redirect URI '{}': {}\", redirect_uri, e))?;\n    let host = redirect_url\n        .host_str()\n        .ok_or_else(|| anyhow::anyhow!(\"Redirect URI '{}' is missing host\", redirect_uri))?\n        .to_string();\n    let port = redirect_url\n        .port_or_known_default()\n        .ok_or_else(|| anyhow::anyhow!(\"Redirect URI '{}' is missing port\", redirect_uri))?;\n    let callback_path = if redirect_url.path().is_empty() {\n        \"/callback\".to_string()\n    } else {\n        redirect_url.path().to_string()\n    };\n    let listener = TcpListener::bind((host.as_str(), port))\n        .await\n        .map_err(|e| anyhow::anyhow!(\"Failed to bind OAuth callback listener on {}:{}: {}\", host, port, e))?;\n\n    Ok((listener, host, callback_path))\n}","sourceCodeStart":200,"sourceCodeEnd":236,"githubUrl":"https://github.com/Kuberwastaken/claurst/blob/b0637c97ec34144387cbf2f74f65df6d16a6cef1/src-rust/crates/mcp/src/oauth.rs#L200-L236","documentation":"url::Url::parse rejected the OAuth redirect_uri configured for the MCP server's OAuth flow (e.g. missing scheme, malformed host, or invalid characters). The URI is used to bind the local callback listener; if it cannot be parsed, no callback can be received.","triggerScenarios":"Passing a malformed redirect_uri to run_mcp_auth_session / bind_callback_listener — e.g. a value without a scheme ('127.0.0.1:8080/callback'), containing spaces or illegal characters, or an empty string read from config.","commonSituations":"Typo in a settings.json redirect URI; hand-built URI missing 'http://'; copying a URI with trailing whitespace or quotes from docs; shell variable interpolation producing an empty value.","solutions":["Print the redirect URI from the error message and fix its syntax (must include scheme, e.g. http://127.0.0.1:PORT/callback)","Use the redirect_uri exactly as registered with the OAuth provider, including scheme and port","Trim whitespace/quotes when reading the URI from config or environment","Construct the URI programmatically (e.g. format!(\"http://127.0.0.1:{}/callback\", port)) instead of hand-typing it"],"exampleFix":"// before\nlet redirect_uri = \"127.0.0.1:8080/callback\";\n// after\nlet redirect_uri = \"http://127.0.0.1:8080/callback\";","handlingStrategy":"validation","validationCode":"fn validate_redirect(uri: &str) -> Result<(), String> {\n    let u = url::Url::parse(uri).map_err(|e| e.to_string())?;\n    if u.scheme() != \"http\" && u.scheme() != \"https\" { return Err(\"scheme must be http(s)\".into()); }\n    Ok(())\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always include the scheme (http://) in redirect URIs","Trim whitespace/quotes when loading URIs from config or env","Keep the URI identical to what is registered with the OAuth provider"],"tags":["oauth","url","config"],"backgroundTag":"invalid-url-format","analyzedSha":"b0637c97ec34144387cbf2f74f65df6d16a6cef1","analyzedAt":"2026-09-10T00:24:58.650Z","contentChangedAt":"2026-09-10T00:24:58.650Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}