Kuberwastaken/claurst · error
valid OAuth authorize base URL
Error message
valid OAuth authorize base URL
What it means
This panic fires when the OAuth authorize base URL passed into the Anthropic OAuth authorize-URL builder cannot be parsed by the `url` crate. The function assumes callers supply an absolute, well-formed HTTP(S) URL and uses expect to convert a parse failure into a panic with the message "valid OAuth authorize base URL".
Solutions
- Print/inspect the `authorize_base` argument; run it through `url::Url::parse` yourself to see the exact parse error.
- Ensure the value is an absolute URL including scheme (e.g. `https://claude.ai/oauth/authorize`), not a relative path or bare host.
- If it comes from user config, validate it at config-load time (parse once, reject invalid values with a clear message).
- Change the function to return `Result<String, url::ParseError>` so a bad base becomes a user-facing error instead of a panic.
Example fix
// before
let mut u = url::Url::parse(authorize_base)
.expect("valid OAuth authorize base URL");
// after
let mut u = url::Url::parse(authorize_base)
.map_err(|e| OAuthError::InvalidAuthorizeUrl(format!("{authorize_base}: {e}")))?; Defensive patterns
Strategy: validation
Validate before calling
// Validate authorize_base before calling the builder:
fn valid_authorize_base(s: &str) -> bool {
url::Url::parse(s)
.map(|u| matches!(u.scheme(), "https" | "http") && u.host_str().is_some())
.unwrap_or(false)
} Try / catch
// Panic, not Result — guard the call site:
let url = std::panic::catch_unwind(|| build_authorize_url(base, &challenge, &state, port, manual))
.map_err(|_| OAuthError::InvalidAuthorizeUrl(base.to_string()))?; Prevention
- Store the authorize base as a parsed url::Url in config, not a raw string
- Reject relative or scheme-less URLs at settings-load time
- Keep the default constant absolute (https://...) and require the same for overrides
- Log the offending string before parsing in debug builds
When it happens
Trigger: Invoking the authorize-URL builder (with code_challenge, state, callback_port, is_manual) with an `authorize_base` that is not a valid absolute URL — e.g. a relative path, an empty string, a URL missing a scheme, or a mistyped constant.
Common situations: A settings/config override pointing the authorize endpoint at a malformed value; trimming or joining logic that stripped the scheme; environments (self-hosted proxies, corporate gateways) where users set a custom authorize base; a refactor changing the constant from absolute to host-relative.
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.
Related errors
- Login succeeded but could not obtain a usable credential
- No LSP server configured for
- Unknown MCP server
- MCP server ' ' has no URL configured (required for OAuth)
- AnthropicProvider::from_config: failed to create…
AI-assisted analysis of Kuberwastaken/claurst@b0637c97ec (2026-09-10).
Data as JSON: /api/errors/a78587ecae5ce426.
Report an issue: GitHub.
Appendix: source
Thrown at src-rust/crates/core/src/lib.rs:4323
let u1 = uuid::Uuid::new_v4();
let u2 = uuid::Uuid::new_v4();
bytes[..16].copy_from_slice(u1.as_bytes());
bytes[16..].copy_from_slice(u2.as_bytes());
base64::engine::general_purpose::URL_SAFE_NO_PAD.encode(bytes)
}
// ---- URL builder ----
/// Build an OAuth authorization URL with all required PKCE parameters.
pub fn build_auth_url(
authorize_base: &str,
code_challenge: &str,
state: &str,
callback_port: u16,
is_manual: bool,
) -> String {
let mut u = url::Url::parse(authorize_base)
.expect("valid OAuth authorize base URL");
{
let mut q = u.query_pairs_mut();
q.append_pair("code", "true"); // tells the login page to show Claude Max upsell
q.append_pair("client_id", CLIENT_ID);
q.append_pair("response_type", "code");
let redirect = if is_manual {
MANUAL_REDIRECT_URL.to_string()
} else {
format!("http://localhost:{}/callback", callback_port)
};
q.append_pair("redirect_uri", &redirect);
q.append_pair("scope", &ALL_SCOPES.join(" "));
q.append_pair("code_challenge", code_challenge);
q.append_pair("code_challenge_method", "S256");
q.append_pair("state", state);
}
u.to_string()
}View on GitHub (pinned to b0637c97ec)