siyuan-note/siyuan · error
OAuth token endpoint returned
Error message
OAuth token endpoint returned %s
What it means
oauthTokenRequest POSTs to the token endpoint and expects either a 2xx JSON token response or an RFC 6749 JSON error body with a non-empty 'error' code. When the status is non-2xx AND the body is not a parseable OAuth error (or lacks the error code), it fails with this generic message including the HTTP status text, because the server's actual rejection reason is unknown.
Solutions
- Verify credential.TokenEndpoint matches the token_endpoint advertised in the authorization server metadata.
- Capture the raw response body (curl the token endpoint) to see the real error page/message.
- Check for WAF/proxy interference (Cloudflare challenges, SSO login HTML) between the client and IdP.
- Confirm TokenAuthMethod (none/client_secret_post/client_secret_basic) is one the IdP accepts; a wrong method can yield opaque 401s.
- Retry during IdP outages; 5xx is usually transient.
Example fix
// before: stale endpoint after IdP migration token_endpoint: "https://old-idp.example.com/oauth/token" // after: use current metadata value token_endpoint: "https://auth.example.com/oauth/token"
Defensive patterns
Strategy: try-catch
Validate before calling
resp, err := http.PostForm(tokenEndpoint, url.Values{"grant_type": {"refresh_token"}, "refresh_token": {tok}})
if err != nil || resp.StatusCode < 200 || resp.StatusCode >= 300 {
// probe the token endpoint manually to see the raw error before refreshing
} Try / catch
cred, permanent, err := refreshOAuthCredential(ctx, client, credential)
if err != nil {
if permanent {
startFreshAuthorizeFlow(server) // invalid_grant/invalid_client
} else {
inspectTokenEndpointRawResponse() // non-protocol error, check body/status
}
} Prevention
- Verify token_endpoint against authorization server metadata during setup
- Test the token endpoint with curl to see raw non-JSON error bodies
- Confirm the configured token auth method is supported by the IdP
- Check WAF/proxy behavior on POSTs to the token endpoint
When it happens
Trigger: Called from refreshOAuthCredential (grant_type=refresh_token) when the token endpoint returns e.g. 500, 403, 404, or an HTML/empty error body with a non-2xx status — anything outside 200-299 that cannot be decoded into an oauthTokenError with a code.
Common situations: Token endpoint URL wrong (404 from a router); IdP returns HTML error page (WAF/Cloudflare challenge); 500 during IdP outage; auth method rejected with a non-protocol 401 body; rate limiting returning plain text.
Related errors
- server returned
- authentication probe returned HTTP " + response.status
- boot progress request returned HTTP " + response.status
- discover OAuth authorization server
- discover OIDC provider failed
AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19).
Data as JSON: /api/errors/bd22070949aeedfc.
Report an issue: GitHub.
Appendix: source
Thrown at kernel/mcp/client/oauth.go:678
if err != nil {
return nil, nil, err
}
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
req.Header.Set("Accept", "application/json")
applyOAuthClientAuthentication(nil, req, credential)
resp, err := client.Do(req)
if err != nil {
return nil, nil, err
}
defer resp.Body.Close()
body, err := io.ReadAll(io.LimitReader(resp.Body, 1<<20))
if err != nil {
return nil, nil, err
}
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
tokenErr := &oauthTokenError{}
if json.Unmarshal(body, tokenErr) != nil || tokenErr.Code == "" {
return nil, nil, fmt.Errorf("OAuth token endpoint returned %s", resp.Status)
}
return nil, tokenErr, tokenErr
}
result := &oauthTokenResponse{}
if err = json.Unmarshal(body, result); err != nil {
return nil, nil, err
}
if result.AccessToken == "" {
return nil, nil, fmt.Errorf("OAuth token endpoint returned no access token")
}
if result.TokenType != "" && !strings.EqualFold(result.TokenType, "Bearer") {
return nil, nil, fmt.Errorf("OAuth token endpoint returned unsupported token type %q", result.TokenType)
}
return result, nil, nil
}
func applyOAuthClientAuthentication(values url.Values, req *http.Request, credential oauthCredential) {
switch credential.TokenAuthMethod {View on GitHub (pinned to 9f775e8a12)