siyuan-note/siyuan · error
OAuth state mismatch
Error message
OAuth state mismatch
What it means
The OAuth state parameter is a random per-flow value used to bind the callback to the initiation request and prevent CSRF. When the callback's state does not equal the state generated for the flow, the library rejects the response as a possible CSRF/interception attempt rather than using the code.
Solutions
- Restart the authorization flow and use only a single browser tab/window for consent
- Do not reuse or bookmark old callback URLs; each flow has a unique state
- Ensure no proxy or extension rewrites query parameters on the localhost callback
- Clear stale tabs of the IdP consent page and retry
Defensive patterns
Strategy: retry
Try / catch
if err := h.Authorize(ctx, true); err != nil {
if strings.Contains(err.Error(), "state mismatch") {
// discard the stale callback and restart a fresh authorization flow
}
} Prevention
- Use a single browser tab per authorization flow and don't reuse old consent tabs
- Never bookmark or replay callback URLs — each contains a one-time state
- Don't start two Authorize flows concurrently for the same server
- Ensure no middleware rewrites query parameters on the localhost callback
When it happens
Trigger: A browser request hits the local callback endpoint whose state query parameter differs from the state stored in oauthFlows for that flowID — a stale/duplicate tab, a replayed redirect, or a forged callback.
Common situations: User completed the flow twice in two tabs so one redirect hits the wrong/expired flow; a bookmarked or replayed callback URL; an attacker-crafted callback; proxy stripping/altering query parameters.
Understand the failure class
Background: Checksum mismatch errors: "checksum verification failed", "digest mismatch", "expected vs actual checksum" — what they mean and how to fix them — this error's family across 41 libraries.
Related errors
- configuration is not initialized
- discover OAuth authorization server
- exchange OAuth authorization code
- mcp oauth authorization required
- OAuth authorization failed
AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19).
Data as JSON: /api/errors/7c7aebe3e7de7b2f.
Report an issue: GitHub.
Appendix: source
Thrown at kernel/mcp/client/oauth.go:389
oauthFlows.Unlock()
defer removeOAuthFlow(flowID, flow)
setMCPRuntimeStateForContext(ctx, h.server.ID, "authorizing", 0, "", authorizationURL)
var callback oauthCallbackResult
timer := time.NewTimer(oauthAuthorizationTimeout)
defer timer.Stop()
select {
case callback = <-flow.Result:
case <-ctx.Done():
return ctx.Err()
case <-timer.C:
return fmt.Errorf("OAuth authorization timed out")
}
if callback.Error != "" {
return fmt.Errorf("OAuth authorization failed: %s", callback.Error)
}
if callback.State != state {
return fmt.Errorf("OAuth state mismatch")
}
if callback.Code == "" {
return fmt.Errorf("OAuth callback did not include an authorization code")
}
exchangeCtx := context.WithValue(ctx, oauth2.HTTPClient, h.client)
token, err := config.Exchange(exchangeCtx, callback.Code,
oauth2.VerifierOption(verifier),
oauth2.SetAuthURLParam("resource", prm.Resource))
if err != nil {
return fmt.Errorf("exchange OAuth authorization code: %w", err)
}
if token.TokenType != "" && !strings.EqualFold(token.TokenType, "Bearer") {
return fmt.Errorf("OAuth token endpoint returned unsupported token type %q", token.TokenType)
}
credential = registrationCredential
credential.TokenAuthMethod = authMethod
credential.AccessToken = token.AccessTokenView on GitHub (pinned to 9f775e8a12)