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

  1. Print/inspect the `authorize_base` argument; run it through `url::Url::parse` yourself to see the exact parse error.
  2. Ensure the value is an absolute URL including scheme (e.g. `https://claude.ai/oauth/authorize`), not a relative path or bare host.
  3. If it comes from user config, validate it at config-load time (parse once, reject invalid values with a clear message).
  4. 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

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


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)