siyuan-note/siyuan · error
OIDC configuration changed during validation
Error message
OIDC configuration changed during validation
What it means
activateOIDCValidation applies the validated candidate config via Conf.CompareAndSetOIDC(transaction.ConfigVersion, transaction.Config). CompareAndSetOIDC performs an optimistic compare-and-swap against the live config version; if the version no longer matches — meaning the OIDC configuration was edited while validation was in progress — the swap fails, the transaction is deleted, and this error is returned.
Solutions
- Re-run the full validation flow (OIDCValidateStart → poll → activate) against the current configuration
- Serialize OIDC configuration edits so validation and save cannot interleave (single-admin workflow or lock the settings panel)
- Surface the error in the UI as 'settings changed, please re-validate' and auto-restart validation
- Compare config versions client-side before activating and warn the user early
Example fix
// before swapped, err := model.OIDCValidateActivate(pollToken, binding) // config edited mid-flow -> "changed during validation" // after // restart validation against the new config start, _ := model.OIDCValidateStart(redirectURL) // poll then activate with the new transaction
Defensive patterns
Strategy: try-catch
Validate before calling
// compare config version before activating
if txn.ConfigVersion != model.OIDCConfigurationVersion() { warnConfigChanged(); restartValidation() } Try / catch
ok, changed, err := model.OIDCValidateActivate(pollToken, binding)
if err != nil && strings.Contains(err.Error(), "changed during validation") {
// settings were edited mid-flow: restart validation against current config
return restartOIDCValidation()
} Prevention
- Avoid editing OIDC settings while a validation flow is in progress
- Serialize admin edits to the auth settings panel
- Show an in-progress indicator during validation to discourage concurrent saves
When it happens
Trigger: An admin saved OIDC settings (bumping the config version) between the start of validation and the OIDCValidateActivate call; concurrent configuration updates from another admin session or via the settings API during the validation window.
Common situations: Two admins editing auth settings simultaneously; an automated config sync rewrites conf while a user is completing validation; user edits another OIDC field in the panel, then submits the previously validated flow.
Understand the failure class
Background: Conflicting config options: "cannot be used together" — configuration validation errors across open-source libraries — this error's family across 162 libraries.
Related errors
- A public HTTPS OIDC redirect URL is required for remote…
- agent session revision conflict
- attribute view order changed; retry the drag
- OIDC client ID is required
- OIDC configuration changed during provider discovery
AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19).
Data as JSON: /api/errors/28ec85e8deebdd9b.
Report an issue: GitHub.
Appendix: source
Thrown at kernel/model/oidc.go:785
oidcTransactions.Lock()
defer oidcTransactions.Unlock()
cleanupOIDCTransactionsLocked()
state := oidcTransactions.byPoll[pollToken]
transaction := oidcTransactions.byState[state]
if transaction == nil || transaction.Flow != oidcFlowValidate || transaction.Binding == "" ||
binding == "" || transaction.Binding != binding || !transaction.Completed || !transaction.Success {
return false, errors.New("OIDC validation transaction was not found or has expired")
}
if transaction.Activated {
return false, nil
}
if transaction.Config == nil {
return false, errors.New("OIDC validation configuration is missing")
}
configurationChanged, swapped := Conf.CompareAndSetOIDC(transaction.ConfigVersion, transaction.Config)
if !swapped {
deleteOIDCTransactionLocked(state)
return false, errors.New("OIDC configuration changed during validation")
}
transaction.Config = nil
transaction.Activated = true
return configurationChanged, nil
}
func cancelOIDCValidation(pollToken, binding string) bool {
oidcTransactions.Lock()
defer oidcTransactions.Unlock()
cleanupOIDCTransactionsLocked()
state := oidcTransactions.byPoll[pollToken]
transaction := oidcTransactions.byState[state]
if transaction == nil || transaction.Flow != oidcFlowValidate || transaction.Activated || transaction.Binding == "" ||
binding == "" || transaction.Binding != binding {
return false
}
deleteOIDCTransactionLocked(state)
return trueView on GitHub (pinned to 9f775e8a12)