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
- Correct the token_url in the OAuth config to a full absolute URL, e.g. https://github.com/login/oauth/access_token
- Confirm the token endpoint against the provider's OAuth documentation (some providers use /oauth/token, others /api/oauth.v2.access)
- Check that the value is not empty — empty strings fail Url::parse with RelativeUrlWithoutBase
- 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
- Validate both auth_url and token_url together when saving a provider config
- Copy token endpoints directly from provider docs to avoid path typos
- Never leave token_url empty — some admin UIs allow partial configs
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.
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- Invalid authorization endpoint URL: {e}
- Invalid redirect URL: {e}
- Invalid Slack authorization URL: {e}
- Invalid Slack token URL: {e}
- ${what} failed:\n${output}
AI-assisted analysis of windmill-labs/windmill@e474e8803c (2026-09-03).
Data as JSON: /api/errors/8950f49e024f331c.
Report an issue: GitHub.