windmill-labs/windmill · error

Invalid token endpoint URL: {e}

Error message

Invalid token endpoint URL: {e}

What it means

Same as the authorization URL check but for the OAuth token endpoint (config.token_url). build_basic_client parses it before constructing the oauth2 OClient; an unparseable value aborts client creation.

Source

Thrown at backend/windmill-oauth/src/lib.rs:336

#[derive(Deserialize)]
pub struct OAuthCallback {
    pub code: String,
    pub state: String,
}

/// Build a basic OAuth client from configuration
pub fn build_basic_client(
    name: String,
    config: OAuthConfig,
    client_params: OAuthClient,
    login: bool,
    base_url: &str,
    override_callback: Option<String>,
) -> error::Result<(String, OClient)> {
    let auth_url = Url::parse(&config.auth_url)
        .map_err(|e| anyhow!("Invalid authorization endpoint URL: {e}"))?;
    let token_url =
        Url::parse(&config.token_url).map_err(|e| anyhow!("Invalid token endpoint URL: {e}"))?;

    let redirect_url = if login {
        format!("{base_url}/user/login_callback/{name}")
    } else if let Some(callback) = override_callback {
        callback
    } else {
        format!("{base_url}/oauth/callback/{name}")
    };

    let mut client = OClient::new(client_params.id, auth_url, token_url);
    if config.req_body_auth.unwrap_or(false) {
        client.set_auth_type(AuthType::RequestBody);
    }
    client.set_client_secret(client_params.secret.clone());
    client.set_redirect_url(
        Url::parse(&redirect_url).map_err(|e| anyhow!("Invalid redirect URL: {e}"))?,
    );

View on GitHub (pinned to e474e8803c)

Solutions

  1. Correct the token_url in the OAuth config to a full absolute URL, e.g. https://github.com/login/oauth/access_token
  2. Confirm the token endpoint against the provider's OAuth documentation (some providers use /oauth/token, others /api/oauth.v2.access)
  3. Check that the value is not empty — empty strings fail Url::parse with RelativeUrlWithoutBase
  4. Restart/re-save the provider config after fixing so the client is rebuilt

Example fix

// before
token_url = "https://github.com"  // missing path
// after
token_url = "https://github.com/login/oauth/access_token"
Defensive patterns

Strategy: validation

Validate before calling

fn valid_token_url(s: &str) -> bool { Url::parse(s).map(|u| u.scheme().starts_with("http")).unwrap_or(false) }

Type guard

fn is_absolute_http_url(s: &str) -> bool {
    Url::parse(s).map(|u| matches!(u.scheme(), "http" | "https")).unwrap_or(false)
}

Try / catch

match build_basic_client(&config, login, base_url, None) {
    Ok(v) => v,
    Err(e) if e.to_string().contains("Invalid token endpoint URL") => {
        // inspect config.token_url, fix and retry
        return Err(e);
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: build_basic_client / build_client_credentials_oauth_client invoked with a config whose token_url is empty, scheme-less, or otherwise invalid per Url::parse.

Common situations: Token endpoint left blank in provider settings while auth URL was filled in; copying only the path (/login/oauth/access_token); self-hosted provider (Keycloak, Auth0) token URL typo'd or pointing at a bare host.

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 windmill-labs/windmill@e474e8803c (2026-09-03). Data as JSON: /api/errors/8950f49e024f331c. Report an issue: GitHub.