siyuan-note/siyuan · error
validate OAuth issuer: %w
Error message
validate OAuth issuer: %w
What it means
Wrapped error at oauth.go:528-530 from auth.GetAuthServerMetadata during validateCredentialIssuer. After PRM discovery confirmed the resource and authorization_servers[0], fetching the AS metadata document itself failed — so the stored credential's Issuer and TokenEndpoint cannot be re-verified.
Source
Thrown at kernel/mcp/client/oauth.go:530
}
func (h *mcpOAuthHandler) validateCredentialIssuer(ctx context.Context, credential oauthCredential) (bool, error) {
var challenges []oauthex.Challenge
resource := h.server.URL
if credential.ResourceMetadataURL != "" {
challenges = []oauthex.Challenge{{Scheme: "bearer", Params: map[string]string{"resource_metadata": credential.ResourceMetadataURL}}}
resource = credential.Resource
}
prm, err := discoverProtectedResource(ctx, challenges, resource, h.client)
if err != nil {
return false, fmt.Errorf("validate OAuth protected resource: %w", err)
}
if prm.Resource != credential.Resource || len(prm.AuthorizationServers) == 0 {
return false, nil
}
asm, err := auth.GetAuthServerMetadata(ctx, prm.AuthorizationServers[0], h.client)
if err != nil {
return false, fmt.Errorf("validate OAuth issuer: %w", err)
}
return asm != nil && asm.Issuer == credential.Issuer && asm.TokenEndpoint == credential.TokenEndpoint, nil
}
func protectedResourceURLs(metadataURL, resource string) []protectedResourceURL {
var result []protectedResourceURL
if metadataURL != "" {
result = append(result, protectedResourceURL{URL: metadataURL, Resource: resource})
}
resourceURL, err := url.Parse(resource)
if err != nil {
return result
}
metadata := *resourceURL
metadata.RawPath = ""
metadata.RawQuery = ""
metadata.Fragment = ""
metadata.Path = "/.well-known/oauth-protected-resource/" + strings.TrimLeft(resourceURL.Path, "/")View on GitHub (pinned to 251596fc0d)
Solutions
- Verify the AS issuer URL listed in authorization_servers[0] serves /.well-known/oauth-authorization-server.
- Retry on transient AS outages; the credential is not cleared, so a later successful validation can restore reuse.
- If the AS issuer changed, update the resource server's authorization_servers and clear the stored credential to force re-discovery.
Defensive patterns
Strategy: retry
Try / catch
// AS metadata fetch failed during credential validation — retry transient outages.
asm, err := auth.GetAuthServerMetadata(ctx, prm.AuthorizationServers[0], h.client)
if err != nil {
if isTransientNetworkErr(err) {
return false, nil // treat as 'cannot validate now'; keep credential, retry later
}
return false, fmt.Errorf("validate OAuth issuer: %w", err)
} Prevention
- Keep the AS issuer metadata endpoint highly available.
- Do not treat a transient AS metadata fetch failure as a credential invalidation.
- Update authorization_servers on the resource when the AS issuer rotates.
When it happens
Trigger: validateCredentialIssuer reaches the auth.GetAuthServerMetadata call (PRM discovery succeeded, Resource matches, AuthorizationServers non-empty) but the AS metadata fetch errors. Returns (false, wrapped error) — caller treats the credential as invalid with cause.
Common situations: AS metadata endpoint (/.well-known/oauth-authorization-server) temporarily down; AS rotated issuer URL not reflected in PRM; network/TLS failure to the AS; AS behind a proxy that 500s on the well-known path.
Related errors
- validate OAuth protected resource: %w
- tools/list returned an empty response
- tools/list repeated cursor %q
- unsupported server type: %s
- command is required for stdio server
AI-assisted analysis of siyuan-note/siyuan@251596fc0d (2026-08-12).
Data as JSON: /api/errors/aecc6af639ce4400.
Report an issue: GitHub.