siyuan-note/siyuan · error

OAuth authorization server does not support the…

Error message

OAuth authorization server does not support the authorization code grant

What it means

The authorization server advertises GrantTypesSupported and it does not include "authorization_code". Since the client exclusively uses the authorization-code grant (optionally with refresh_token), such a server cannot complete MCP authorization and the flow is aborted.

Solutions

  1. Enable the authorization_code grant type on the authorization server / client policy
  2. Correct the grant_types_supported metadata if the grant is actually available
  3. Choose an OAuth provider configuration that supports user-interactive authorization code grants, as MCP requires
Defensive patterns

Strategy: validation

Validate before calling

if len(asm.GrantTypesSupported) > 0 && !slices.Contains(asm.GrantTypesSupported, "authorization_code") {
    return errors.New("IdP does not allow the authorization code grant")
}

Try / catch

if err := h.Authorize(ctx, req, resp); err != nil && strings.Contains(err.Error(), "authorization code grant") {
    reportIdPConfigIssue(err)
}

Prevention

When it happens

Trigger: Interactive Authorize passes PKCE and response-type checks, but asm.GrantTypesSupported is non-empty and omits "authorization_code" — e.g. metadata lists only ["client_credentials", "refresh_token"].

Common situations: IdP restricted to machine-to-machine grants (client_credentials only); admin disabled the authorization code grant in the IdP policy; metadata misconfiguration.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19). Data as JSON: /api/errors/edd75cb8bd37fdb1. Report an issue: GitHub.

Appendix: source

Thrown at kernel/mcp/client/oauth.go:258

		credential.AccessToken = ""
		credential.RefreshToken = ""
		credential.Expiry = time.Time{}
		if saveErr := putOAuthCredential(credential); saveErr != nil {
			logging.LogWarnf("mcp oauth: clear invalid credentials failed: %s", saveErr)
		}
	}
	if !interactive {
		setMCPRuntimeStateForContext(ctx, h.server.ID, "authorization_required", 0, "", "")
		return errOAuthAuthorizationRequired
	}
	if !slices.Contains(asm.CodeChallengeMethodsSupported, "S256") {
		return fmt.Errorf("OAuth authorization server does not support PKCE S256")
	}
	if len(asm.ResponseTypesSupported) > 0 && !slices.Contains(asm.ResponseTypesSupported, "code") {
		return fmt.Errorf("OAuth authorization server does not support the authorization code response type")
	}
	if len(asm.GrantTypesSupported) > 0 && !slices.Contains(asm.GrantTypesSupported, "authorization_code") {
		return fmt.Errorf("OAuth authorization server does not support the authorization code grant")
	}

	flowID := reusableOAuthFlowID(credential)
	if flowID == "" {
		flowID, err = secureRandomString(24)
		if err != nil {
			return err
		}
	}
	state, err := secureRandomString(24)
	if err != nil {
		return err
	}
	callbackURL := fmt.Sprintf("http://127.0.0.1:%s/api/ai/mcp/oauth/callback/%s", util.ServerPort, flowID)
	scopes := append([]string(nil), prm.ScopesSupported...)
	if len(scopes) == 0 {
		scopes = append(scopes, asm.ScopesSupported...)
	}

View on GitHub (pinned to 9f775e8a12)