{"record":{"id":"8732c50d6b653d71","repo":"siyuan-note/siyuan","slug":"oauth-authorization-server-metadata-not-found","errorCode":null,"errorMessage":"OAuth authorization server metadata not found","messagePattern":"OAuth authorization server metadata not found","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/mcp/client/oauth.go","lineNumber":217,"sourceCode":"\tif interactive {\n\t\tdefer func() {\n\t\t\tif retErr != nil && !errors.Is(retErr, context.Canceled) {\n\t\t\t\tsetMCPRuntimeStateForContext(ctx, h.server.ID, \"authorization_required\", 0, retErr.Error(), \"\")\n\t\t\t}\n\t\t}()\n\t}\n\n\tprm, err := discoverProtectedResource(ctx, challenges, req.URL.String(), h.client)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tasm, err := auth.GetAuthServerMetadata(ctx, prm.AuthorizationServers[0], h.client)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"discover OAuth authorization server: %w\", err)\n\t}\n\tif asm == nil {\n\t\treturn fmt.Errorf(\"OAuth authorization server metadata not found\")\n\t}\n\tcredential, hasCredential := getOAuthCredential(h.server.ID, h.server.URL)\n\tif hasCredential && credential.Issuer == asm.Issuer {\n\t\tcredential.TokenEndpoint = asm.TokenEndpoint\n\t\tcredential.RevocationEndpoint = asm.RevocationEndpoint\n\t}\n\tif hasCredential && credential.Issuer == asm.Issuer && credential.RefreshToken != \"\" &&\n\t\tchallengeError != \"insufficient_scope\" && !credential.Rejected && !oauthClientRegistrationExpired(credential) {\n\t\trefreshed, permanent, refreshErr := refreshOAuthCredential(ctx, h.client, credential)\n\t\tif refreshErr == nil {\n\t\t\tif saveErr := putOAuthCredential(refreshed); saveErr != nil {\n\t\t\t\tlogging.LogWarnf(\"mcp oauth: save refreshed credentials failed: %s\", saveErr)\n\t\t\t}\n\t\t\th.sourceMu.Lock()\n\t\t\th.source = &storedOAuthTokenSource{credential: refreshed, client: h.client}\n\t\t\th.sourceMu.Unlock()\n\t\t\tsetMCPRuntimeStateForContext(ctx, h.server.ID, \"oauth_retrying\", 0, \"\", \"\")\n\t\t\treturn nil","sourceCodeStart":199,"sourceCodeEnd":235,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/mcp/client/oauth.go#L199-L235","documentation":"GetAuthServerMetadata returned no error but also a nil metadata object. The library treats a missing metadata document as fatal because the whole flow (endpoints, PKCE support, registration endpoint) depends on it. This catches servers that return 200 with an empty/unparseable body in a way that yields nil instead of an error.","triggerScenarios":"Authorize calls GetAuthServerMetadata on prm.AuthorizationServers[0] and receives (nil, nil) — e.g. the discovery helper resolves no metadata for the issuer URL without treating it as an error.","commonSituations":"IdP serves an empty 200 for the well-known URL; a misconfigured wildcard route returns an empty page; issuer URL is a bare domain with no metadata route; OIDC discovery disabled on the server.","solutions":["Confirm the authorization server publishes RFC 8414 metadata at /.well-known/oauth-authorization-server and that it returns a JSON document","Correct the authorization_servers URL in the protected-resource metadata","Upgrade or reconfigure the IdP so discovery metadata is enabled","Clear any cached/broken protected-resource metadata (discoverProtectedResource output) and retry"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"meta, err := auth.GetAuthServerMetadata(ctx, authServerURL, http.DefaultClient)\nif err != nil || meta == nil {\n    return errors.New(\"authorization server metadata unavailable\")\n}","typeGuard":"if asm == nil {\n    return errors.New(\"OAuth authorization server metadata not found\")\n}","tryCatchPattern":"if err := h.Authorize(ctx, req, resp); err != nil && strings.Contains(err.Error(), \"metadata not found\") {\n    promptUserToVerifyIdPDiscovery()\n}","preventionTips":["Confirm the IdP serves non-empty RFC 8414 metadata before registering the MCP server","Avoid bare-domain issuer URLs without a discovery route","Watch for wildcard routes that answer 200 with empty bodies on well-known paths"],"tags":["oauth","mcp","discovery","metadata"],"backgroundTag":"empty-api-response","analyzedSha":"9f775e8a12daef8255556097396f9b2739078892","analyzedAt":"2026-09-19T03:17:15.984Z","contentChangedAt":"2026-09-19T03:17:15.984Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}