siyuan-note/siyuan · error
discover OIDC provider failed
Error message
discover OIDC provider failed: %w
What it means
New performs OIDC discovery by fetching {issuerURL}/.well-known/openid-configuration via go-oidc's oidc.NewProvider; any failure (DNS, TLS, HTTP status, malformed discovery document) is wrapped as "discover OIDC provider failed" with the underlying error. This means the kernel could not retrieve or parse the IdP's discovery metadata, so the OIDC endpoints and keys are unknown.
Solutions
- Verify the issuer URL is exactly what the IdP advertises (check https://<issuer>/.well-known/openid-configuration loads and matches the issuer claim).
- Confirm network reachability from the kernel host: curl the discovery URL from the same machine/container.
- Fix TLS trust: install the internal CA into the system trust store or provide proper certificates; check for expired certs.
- Check proxy/DNS settings for the kernel process and retry after the IdP (or its outage) is restored.
- Read the wrapped cause after the colon in the message to identify DNS vs TLS vs HTTP vs parse failure.
Example fix
// before
cfg := &conf.OIDC{Provider: conf.OIDCProviderCustom, IssuerURL: "https://sso.internal/keycloak"} // wrong path, discovery 404s
provider, err := New(cfg, redirectURL)
// after
cfg := &conf.OIDC{Provider: conf.OIDCProviderCustom, IssuerURL: "https://sso.internal/realms/main"} // matches .well-known/openid-configuration location
provider, err := New(cfg, redirectURL) Defensive patterns
Strategy: retry
Validate before calling
resp, err := http.Get(strings.TrimSuffix(issuerURL, "/") + "/.well-known/openid-configuration")
if err != nil || resp.StatusCode != http.StatusOK {
return errors.New("issuer discovery endpoint is not reachable from this host")
} Try / catch
provider, err := New(cfg, redirectURL)
if err != nil {
if strings.Contains(err.Error(), "discover OIDC provider failed") {
// retry with backoff for transient network issues; otherwise surface the wrapped cause
}
return err
} Prevention
- Curl the discovery URL from the kernel host before configuring the provider
- Install internal CA certificates into containers using the kernel
- Keep NTP synchronized and verify the issuer URL matches the IdP's advertised issuer exactly
- Document firewall/proxy requirements for the token and discovery endpoints
When it happens
Trigger: Calling New where oidc.NewProvider(ctx, issuerURL) fails: issuer URL typo, IdP unreachable, self-signed/expired TLS certificate, discovery endpoint returning non-200, or a document missing required fields (e.g. no jwks_uri).
Common situations: Self-hosted Keycloak/Auth0/Dex behind a firewall or VPN the kernel cannot reach; internal CA certificates not trusted by the container; wrong realm or tenant in the issuer path; IdP serving discovery only on a different external URL; DNS or proxy misconfiguration in Docker/Kubernetes.
Understand the failure class
Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.
Related errors
- proxy returned unexpected tunnel data
- authentication probe returned HTTP " + response.status
- boot progress request returned HTTP " + response.status
- Desktop OIDC login requires a loopback listener
- discover OAuth authorization server
AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19).
Data as JSON: /api/errors/789ce9167be8e57a.
Report an issue: GitHub.
Appendix: source
Thrown at kernel/model/oidc_provider/provider.go:65
}
issuerURL := strings.TrimSpace(config.IssuerURL)
switch config.Provider {
case conf.OIDCProviderGoogle:
issuerURL = googleIssuer
case conf.OIDCProviderMicrosoft:
// Microsoft 多租户端点的 issuer 会随租户变化,必须使用租户专属 issuer。
case conf.OIDCProviderCustom:
case conf.OIDCProviderGitHub:
return newGitHub(config, redirectURL), nil
default:
return nil, fmt.Errorf("unsupported OIDC provider [%s]", config.Provider)
}
if issuerURL == "" {
return nil, errors.New("OIDC issuer URL is required")
}
discovered, err := oidc.NewProvider(ctx, issuerURL)
if err != nil {
return nil, fmt.Errorf("discover OIDC provider failed: %w", err)
}
scopes := append([]string{}, config.Scopes...)
if !contains(scopes, oidc.ScopeOpenID) {
scopes = append([]string{oidc.ScopeOpenID}, scopes...)
}
return &Provider{
kind: conf.OIDCProviderCustom,
oauth2Config: &oauth2.Config{
ClientID: config.ClientID,
ClientSecret: config.ClientSecret,
Endpoint: discovered.Endpoint(),
RedirectURL: redirectURL,
Scopes: scopes,
},
verifier: discovered.Verifier(&oidc.Config{ClientID: config.ClientID}),
}, nil
}
View on GitHub (pinned to 9f775e8a12)