{"record":{"id":"789ce9167be8e57a","repo":"siyuan-note/siyuan","slug":"discover-oidc-provider-failed-w","errorCode":null,"errorMessage":"discover OIDC provider failed: %w","messagePattern":"discover OIDC provider failed: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/oidc_provider/provider.go","lineNumber":65,"sourceCode":"\t}\n\tissuerURL := strings.TrimSpace(config.IssuerURL)\n\tswitch config.Provider {\n\tcase conf.OIDCProviderGoogle:\n\t\tissuerURL = googleIssuer\n\tcase conf.OIDCProviderMicrosoft:\n\t\t// Microsoft 多租户端点的 issuer 会随租户变化，必须使用租户专属 issuer。\n\tcase conf.OIDCProviderCustom:\n\tcase conf.OIDCProviderGitHub:\n\t\treturn newGitHub(config, redirectURL), nil\n\tdefault:\n\t\treturn nil, fmt.Errorf(\"unsupported OIDC provider [%s]\", config.Provider)\n\t}\n\tif issuerURL == \"\" {\n\t\treturn nil, errors.New(\"OIDC issuer URL is required\")\n\t}\n\tdiscovered, err := oidc.NewProvider(ctx, issuerURL)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"discover OIDC provider failed: %w\", err)\n\t}\n\tscopes := append([]string{}, config.Scopes...)\n\tif !contains(scopes, oidc.ScopeOpenID) {\n\t\tscopes = append([]string{oidc.ScopeOpenID}, scopes...)\n\t}\n\treturn &Provider{\n\t\tkind: conf.OIDCProviderCustom,\n\t\toauth2Config: &oauth2.Config{\n\t\t\tClientID:     config.ClientID,\n\t\t\tClientSecret: config.ClientSecret,\n\t\t\tEndpoint:     discovered.Endpoint(),\n\t\t\tRedirectURL:  redirectURL,\n\t\t\tScopes:       scopes,\n\t\t},\n\t\tverifier: discovered.Verifier(&oidc.Config{ClientID: config.ClientID}),\n\t}, nil\n}\n","sourceCodeStart":47,"sourceCodeEnd":83,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/251596fc0de2f9528c00c224252fd073a99973f4/kernel/model/oidc_provider/provider.go#L47-L83","documentation":"Thrown when oidc.NewProvider(ctx, issuerURL) fails during OIDC discovery. The underlying go-oidc library fetches the provider's /.well-known/openid-configuration endpoint and parses it; any network, TLS, DNS, timeout, or malformed-response failure is wrapped with %w for the caller to inspect. This is a runtime/environment error, not a configuration validation error.","triggerScenarios":"The provider constructor calls oidc.NewProvider which performs an HTTP GET on the issuer's discovery endpoint. This fails when: the issuer URL is unreachable, the server returns a non-200 or invalid JSON, TLS certificate verification fails, DNS resolution fails, or the context deadline is exceeded.","commonSituations":"The SiYuan server has no internet access or is behind a firewall blocking outbound HTTPS to the provider. The issuer URL has a self-signed or expired TLS certificate. The issuer URL is mistyped (valid hostname but wrong path). The provider's discovery endpoint is temporarily down. DNS misconfiguration in the container/host.","solutions":["Verify the issuer URL is correct by curling it: curl -v <issuerURL>/.well-known/openid-configuration","Ensure the SiYuan host can reach the provider over HTTPS (check firewall, proxy, DNS).","If using a self-signed certificate, configure the appropriate CA trust on the host or set the system root CAs.","Inspect the wrapped error (err) for the underlying cause — it will contain the HTTP status or network error.","If behind a corporate proxy, ensure HTTP_PROXY/HTTPS_PROXY environment variables are set for the kernel process."],"exampleFix":"// before\nprovider, err := oidc_provider.New(ctx, config, redirectURL)\nif err != nil {\n    log.Printf(\"OIDC init failed: %v\", err)\n}\n\n// after\nprovider, err := oidc_provider.New(ctx, config, redirectURL)\nif err != nil {\n    var discoverErr *fmt.wrapError\n    if strings.Contains(err.Error(), \"discover OIDC provider\") {\n        log.Printf(\"OIDC discovery failed — check issuer URL [%s] and network connectivity: %v\", config.IssuerURL, err)\n    }\n    return\n}","handlingStrategy":"retry","validationCode":"// Pre-flight: verify issuer discovery endpoint is reachable\ndiscoveryURL := strings.TrimRight(issuerURL, \"/\") + \"/.well-known/openid-configuration\"\nresp, err := http.Head(discoveryURL)\nif err != nil || resp.StatusCode != 200 {\n    return nil, fmt.Errorf(\"OIDC discovery endpoint unreachable at %s\", discoveryURL)\n}","typeGuard":null,"tryCatchPattern":"provider, err := oidc_provider.New(ctx, config, redirectURL)\nif err != nil {\n    if strings.Contains(err.Error(), \"discover OIDC provider\") {\n        // Network or provider issue — safe to retry after a delay\n        time.Sleep(2 * time.Second)\n        provider, err = oidc_provider.New(ctx, config, redirectURL)\n        if err != nil {\n            log.Printf(\"OIDC discovery failed after retry: %v\", err)\n            return\n        }\n    }\n}","preventionTips":["Ensure outbound HTTPS connectivity from the SiYuan host to the OIDC provider.","Verify TLS certificates are valid and trusted by the system CA store.","Set appropriate timeouts on the context passed to New().","Test discovery manually with curl before configuring SiYuan."],"tags":["oidc","authentication","network","tls","discovery","runtime"],"backgroundTag":null,"analyzedSha":"251596fc0de2f9528c00c224252fd073a99973f4","analyzedAt":"2026-08-12T21:18:37.123Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}