BoundaryML/baml · error
CSRF state mismatch
Error message
CSRF state mismatch
What it means
During the PropelAuth OAuth authorization-code flow, the CLI's local callback server receives a `state` parameter that does not match the random state the CLI generated. This CSRF protection check fails to prevent cross-site request forgery / response mixing attacks on the redirect.
Solutions
- Close all stale login tabs and restart `baml login` from scratch in one tab
- Ensure the full callback URL including the state parameter reaches the local server (disable interfering extensions/proxies)
- Retry the login after clearing browser cookies for the auth domain
Defensive patterns
Strategy: retry
Try / catch
try {
await login();
} catch (e) {
if (String(e).includes('CSRF state mismatch')) {
closeStaleTabs();
await login(); // retry once with fresh state
}
} Prevention
- Run only one login flow at a time
- Restart login after any timeout instead of reusing old redirect URLs
- Avoid extensions/proxies that rewrite callback query parameters
When it happens
Trigger: The browser redirects to the local callback with a stale or tampered state value; another login tab completing a flow that overwrote the expected state; the auth server dropping or altering the state query parameter.
Common situations: User logs in twice with two tabs; browser extension or proxy strips query params; retrying login after a previous timed-out attempt; manually pasting a callback URL from an older attempt.
Related errors
- active BAML toolchain does not include…
- ` ` already exists. Refusing to overwrite an existing…
- archive contains unsafe path
- are mutually exclusive dispatch modes — pick one.
- artifact URL must use HTTPS
AI-assisted analysis of BoundaryML/baml@bd85ce9dee (2026-09-12).
Data as JSON: /api/errors/11be86c3268985d5.
Report an issue: GitHub.
Appendix: source
Thrown at engine/cli/src/propelauth.rs:158
Err(e) => {
log::debug!("Error opening browser: {e:#}");
println!(" An error occurred while opening the browser.");
println!();
println!(" Click here to login:\n\n{auth_url}");
}
}
} else {
println!(" Click here to login:\n\n{auth_url}");
}
// Wait for the code from the channel
let params = rx
.recv()
.await
.context("Timed out waiting for the authorization server")?;
if params.state != state {
anyhow::bail!("CSRF state mismatch");
}
log::debug!("Received authorization callback: {params:?}");
Ok((params.code, redirect_uri))
}
pub(crate) async fn request_access_token(
&self,
code: &str,
redirect_uri: &str,
code_verifier: &str,
) -> Result<GetAccessTokenResponse> {
// Make the POST request
let client = baml_runtime::request::create_client()?;
let response = client
.post(format!("{}/propelauth/oauth/token", self.auth_url))
.header("Content-Type", "application/x-www-form-urlencoded")
.form(&[View on GitHub (pinned to bd85ce9dee)