siyuan-note/siyuan · error
OAuth callback did not include an authorization code
Error message
OAuth callback did not include an authorization code
What it means
Returned at oauth.go:391-392 when the callback has no error and the state matched, but the code parameter is empty. Per OAuth2 the AS must return either an error or a code; reaching this branch means the AS issued a non-conformant redirect.
Source
Thrown at kernel/mcp/client/oauth.go:392
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.AccessToken
credential.RefreshToken = token.RefreshToken
credential.TokenType = token.TokenType
credential.Expiry = token.ExpiryView on GitHub (pinned to 251596fc0d)
Solutions
- Inspect the actual redirect URL the AS issued to confirm it includes the code parameter.
- Check for proxies or middleware between the AS and SiYuan that may strip query params from the loopback callback.
- Report to the AS operator: a standards-compliant authorization-code redirect must include a non-empty code when no error is present.
Defensive patterns
Strategy: validation
Try / catch
// After matching state, require a non-empty code; otherwise the AS is non-conformant.
if callback.Code == "" {
return fmt.Errorf("OAuth callback did not include an authorization code") // not retriable; report AS bug
} Prevention
- Verify the AS issues standards-compliant authorization-code redirects.
- Inspect for proxies or browser extensions stripping query parameters from the loopback redirect.
When it happens
Trigger: The AS redirected to the callback without ?error and without ?code — e.g. it sent only state, or used a non-standard parameter name, or stripped code from a malformed redirect.
Common situations: AS bug; a reverse proxy/load balancer that strips query parameters; custom login handler on the AS that constructs the redirect incorrectly; browser extension interfering with the redirect URL.
Related errors
- OAuth authorization timed out
- OAuth authorization failed: %s
- OAuth state mismatch
- OAuth flow is missing or expired
- tools/list returned an empty response
AI-assisted analysis of siyuan-note/siyuan@251596fc0d (2026-08-12).
Data as JSON: /api/errors/662c77e0960ff2cc.
Report an issue: GitHub.