siyuan-note/siyuan · error

OIDC issuer URL is required

Error message

OIDC issuer URL is required

What it means

After resolving the issuer URL (explicitly configured, or defaulted for Google/Microsoft), New requires it to be non-empty before attempting OIDC discovery. Only the Custom provider can leave IssuerURL empty in the config, so this error means a custom-provider configuration was saved without the issuer endpoint. Discovery cannot proceed without a base issuer URL.

Solutions

  1. Set IssuerURL in the OIDC config to the IdP's issuer base URL (e.g. https://accounts.example.com), typically the value in the IdP's .well-known/openid-configuration location minus the well-known suffix.
  2. Trim or remove whitespace-only values; the code trims but rejects blank strings.
  3. Validate the issuer URL field as required whenever provider == custom in the settings UI.
  4. If you meant a hosted provider, switch config.Provider to Google/Microsoft/GitHub which have built-in issuers.

Example fix

// before
cfg := &conf.OIDC{Provider: conf.OIDCProviderCustom, IssuerURL: ""}
provider, err := New(cfg, redirectURL)
// after
cfg := &conf.OIDC{Provider: conf.OIDCProviderCustom, IssuerURL: "https://sso.example.com/realms/main"}
provider, err := New(cfg, redirectURL)
Defensive patterns

Strategy: validation

Validate before calling

if cfg.Provider == conf.OIDCProviderCustom && strings.TrimSpace(cfg.IssuerURL) == "" {
    return errors.New("issuer URL is required for the custom OIDC provider")
}

Try / catch

if err != nil {
    if strings.Contains(err.Error(), "issuer URL is required") {
        // mark the IssuerURL field as the offending setting
    }
    return err
}

Prevention

When it happens

Trigger: Calling New with config.Provider == conf.OIDCProviderCustom and strings.TrimSpace(config.IssuerURL) == "" — i.e. the Custom OIDC provider selected but the issuer URL field left blank.

Common situations: Admin selected "Custom" in the settings dialog but skipped the IssuerURL field; whitespace-only value pasted into the field; config JSON hand-edited and the key dropped; issuer URL cleared during troubleshooting and the config saved anyway.

Understand the failure class

Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.

Related errors


AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19). Data as JSON: /api/errors/fcdecd61c814ef8a. Report an issue: GitHub.

Appendix: source

Thrown at kernel/model/oidc_provider/provider.go:61

		return nil, errors.New("OIDC redirect URL is required")
	}
	if config.Provider == conf.OIDCProviderGitHub && config.ClientSecret == "" {
		return nil, errors.New("GitHub OAuth client secret is required")
	}
	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,
		},

View on GitHub (pinned to 9f775e8a12)