siyuan-note/siyuan · error

OIDC configuration changed during provider discovery

Error message

OIDC configuration changed during provider discovery

What it means

getOIDCProvider performs OIDC provider discovery over the network and caches the result keyed by the configuration version plus redirect URL. Before storing a newly discovered provider, it re-checks that the OIDC configuration hash is still the same as when discovery started. If the configuration was modified while discovery was in flight, the stale provider is discarded and this error is thrown.

Solutions

  1. Retry the OIDC login once the configuration change has settled — the new attempt will use the new configuration version
  2. Avoid saving OIDC configuration changes while logins are in progress; apply changes during a maintenance window
  3. If it happens repeatedly, check for clients or scripts that rewrite the config concurrently
Defensive patterns

Strategy: retry

Validate before calling

// Snapshot the config version before starting login and compare after any retryable failure
version := oidcConfigurationVersion(Conf.GetOIDC())

Try / catch

provider, err := getOIDCProvider(ctx, redirectURL)
if err != nil && strings.Contains(err.Error(), "configuration changed") {
    time.Sleep(500 * time.Millisecond)
    provider, err = getOIDCProvider(ctx, redirectURL) // retry with the new config version
}

Prevention

When it happens

Trigger: OIDCStart or finishOIDCExchange triggers getOIDCProvider, and during the (up to oidcProviderTimeout) discovery HTTP round-trip another session/request saves a change to the OIDC settings (issuer, client ID/secret, redirect URL, etc.).

Common situations: An administrator edits OIDC settings while users are concurrently logging in; two overlapping configuration-save requests; automated config tooling flipping values during a login.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


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

Appendix: source

Thrown at kernel/model/oidc.go:609

	if oidcProviders.version != version {
		oidcProviders.version = version
		oidcProviders.items = map[string]*oidc_provider.Provider{}
	}
	if provider := oidcProviders.items[key]; provider != nil {
		oidcProviders.Unlock()
		return provider, nil
	}
	oidcProviders.Unlock()
	discoveryContext, cancel := context.WithTimeout(ctx, oidcProviderTimeout)
	defer cancel()
	provider, err := oidc_provider.New(discoveryContext, Conf.GetOIDC(), redirectURL)
	if err != nil {
		return nil, err
	}
	oidcProviders.Lock()
	defer oidcProviders.Unlock()
	if oidcProviders.version != version || oidcConfigurationVersion(Conf.GetOIDC()) != version {
		return nil, errors.New("OIDC configuration changed during provider discovery")
	}
	if existing := oidcProviders.items[key]; existing != nil {
		return existing, nil
	}
	if len(oidcProviders.items) >= oidcProviderCacheMax {
		oidcProviders.items = map[string]*oidc_provider.Provider{}
	}
	oidcProviders.items[key] = provider
	return provider, nil
}

func newOIDCTransaction(input *oidcStartInput, binding, clientIP, redirectURL string) (*oidcTransaction, error) {
	state, err := secureRandomToken(32)
	if err != nil {
		return nil, err
	}
	nonce, err := secureRandomToken(32)
	if err != nil {

View on GitHub (pinned to 9f775e8a12)