siyuan-note/siyuan · error
validate OAuth protected resource
Error message
validate OAuth protected resource: %w
What it means
validateCredentialIssuer wraps any failure from discoverProtectedResource with the 'validate OAuth protected resource' prefix. It means the stored OAuth credential could not be re-validated because the protected resource metadata could not be fetched (or reported no authorization server). The credential itself is left untouched; validation simply returns false with this error.
Solutions
- Check server reachability and that its /.well-known/oauth-protected-resource metadata endpoint still returns valid JSON.
- Retry later if it is a transient network error — validation failures are not necessarily permanent.
- Re-authenticate from scratch (start a new Authorize flow) so fresh metadata URLs are discovered and stored.
- Update the stored credential's ResourceMetadataURL if the server moved its metadata endpoint.
- Inspect the wrapped error (%w chain) for the real fetch failure cause.
Example fix
// before: assuming stored credential is always valid
// after: handle validation failure by falling back to a fresh authorize flow
valid, err := handler.validateCredentialIssuer(ctx, credential)
if err != nil || !valid {
credential, err = handler.authorize(ctx) // re-run OAuth discovery
} Defensive patterns
Strategy: retry
Validate before calling
if _, err := http.Get(credential.ResourceMetadataURL); err != nil {
// defer re-validation until network/IdP is reachable
} Try / catch
valid, err := handler.validateCredentialIssuer(ctx, credential)
if err != nil {
if isTransient(err) { scheduleRetry() } else { startFreshAuthorizeFlow() }
} Prevention
- Distinguish transient fetch failures from permanent metadata removal via the wrapped error
- Re-run discovery from scratch instead of trusting stored metadata URLs after server upgrades
- Monitor MCP server availability before token refresh windows
- Keep ResourceMetadataURL in sync with the server's actual metadata location
When it happens
Trigger: TokenSource calls validateCredentialIssuer before reusing a stored credential. Thrown when discoverProtectedResource returns the 'metadata not found' or 'metadata has no authorization server' error — i.e. metadata fetch fails for all candidate URLs during credential re-validation.
Common situations: The MCP server went offline or was reconfigured to drop OAuth metadata; temporary network outage while refreshing a token; credential's ResourceMetadataURL now 404s after a server upgrade; DNS or proxy issues.
Understand the failure class
Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.
Related errors
- discover OAuth authorization server
- OAuth protected resource metadata not found
- validate OAuth issuer
- OAuth authorization server metadata not found
- OAuth protected resource metadata has no authorization…
AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19).
Data as JSON: /api/errors/4099c98f9273ef9d.
Report an issue: GitHub.
Appendix: source
Thrown at kernel/mcp/client/oauth.go:523
}
if len(prm.AuthorizationServers) == 0 {
return nil, fmt.Errorf("OAuth protected resource metadata has no authorization server")
}
return &discoveredProtectedResource{ProtectedResourceMetadata: prm, MetadataURL: candidate.URL}, nil
}
return nil, fmt.Errorf("OAuth protected resource metadata not found")
}
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 {View on GitHub (pinned to 9f775e8a12)