Kuberwastaken/claurst · error · anyhow::Error
Failed to parse redirect URI
Error message
Failed to parse redirect URI '{}': {} What it means
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.
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
Example fix
// before let redirect_uri = "127.0.0.1:8080/callback"; // after let redirect_uri = "http://127.0.0.1:8080/callback";
Defensive patterns
Strategy: validation
Validate before calling
fn validate_redirect(uri: &str) -> Result<(), String> {
let u = url::Url::parse(uri).map_err(|e| e.to_string())?;
if u.scheme() != "http" && u.scheme() != "https" { return Err("scheme must be http(s)".into()); }
Ok(())
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: "Invalid URL" errors: why new URL(), URI.parse, and reqwest::Url reject your string — missing scheme, whitespace, and bad path format — this error's family across 39 libraries.
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- MCP server ' ' is configured as ' ' but missing URL
- Redirect URI ' ' is missing host
- No query string in callback
- Redirect URI ' ' is missing port
- Failed to parse OAuth callback URL
AI-assisted analysis of Kuberwastaken/claurst@b0637c97ec (2026-09-10).
Data as JSON: /api/errors/08ebf11f60e136a7.
Report an issue: GitHub.
Appendix: source
Thrown at src-rust/crates/mcp/src/oauth.rs:218
&metadata.authorization_endpoint,
&redirect_uri,
&verifier,
);
Ok(McpAuthSession {
server_name: server_name.to_string(),
auth_url,
redirect_uri,
verifier,
metadata,
})
}
async fn bind_callback_listener(
redirect_uri: &str,
) -> anyhow::Result<(TcpListener, String, String)> {
let redirect_url = url::Url::parse(redirect_uri)
.map_err(|e| anyhow::anyhow!("Failed to parse redirect URI '{}': {}", redirect_uri, e))?;
let host = redirect_url
.host_str()
.ok_or_else(|| anyhow::anyhow!("Redirect URI '{}' is missing host", redirect_uri))?
.to_string();
let port = redirect_url
.port_or_known_default()
.ok_or_else(|| anyhow::anyhow!("Redirect URI '{}' is missing port", redirect_uri))?;
let callback_path = if redirect_url.path().is_empty() {
"/callback".to_string()
} else {
redirect_url.path().to_string()
};
let listener = TcpListener::bind((host.as_str(), port))
.await
.map_err(|e| anyhow::anyhow!("Failed to bind OAuth callback listener on {}:{}: {}", host, port, e))?;
Ok((listener, host, callback_path))
}View on GitHub (pinned to b0637c97ec)