{"record":{"id":"28ec85e8deebdd9b","repo":"siyuan-note/siyuan","slug":"oidc-configuration-changed-during-validation","errorCode":null,"errorMessage":"OIDC configuration changed during validation","messagePattern":"OIDC configuration changed during validation","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/oidc.go","lineNumber":785,"sourceCode":"\toidcTransactions.Lock()\n\tdefer oidcTransactions.Unlock()\n\tcleanupOIDCTransactionsLocked()\n\tstate := oidcTransactions.byPoll[pollToken]\n\ttransaction := oidcTransactions.byState[state]\n\tif transaction == nil || transaction.Flow != oidcFlowValidate || transaction.Binding == \"\" ||\n\t\tbinding == \"\" || transaction.Binding != binding || !transaction.Completed || !transaction.Success {\n\t\treturn false, errors.New(\"OIDC validation transaction was not found or has expired\")\n\t}\n\tif transaction.Activated {\n\t\treturn false, nil\n\t}\n\tif transaction.Config == nil {\n\t\treturn false, errors.New(\"OIDC validation configuration is missing\")\n\t}\n\tconfigurationChanged, swapped := Conf.CompareAndSetOIDC(transaction.ConfigVersion, transaction.Config)\n\tif !swapped {\n\t\tdeleteOIDCTransactionLocked(state)\n\t\treturn false, errors.New(\"OIDC configuration changed during validation\")\n\t}\n\ttransaction.Config = nil\n\ttransaction.Activated = true\n\treturn configurationChanged, nil\n}\n\nfunc cancelOIDCValidation(pollToken, binding string) bool {\n\toidcTransactions.Lock()\n\tdefer oidcTransactions.Unlock()\n\tcleanupOIDCTransactionsLocked()\n\tstate := oidcTransactions.byPoll[pollToken]\n\ttransaction := oidcTransactions.byState[state]\n\tif transaction == nil || transaction.Flow != oidcFlowValidate || transaction.Activated || transaction.Binding == \"\" ||\n\t\tbinding == \"\" || transaction.Binding != binding {\n\t\treturn false\n\t}\n\tdeleteOIDCTransactionLocked(state)\n\treturn true","sourceCodeStart":767,"sourceCodeEnd":803,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/model/oidc.go#L767-L803","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nswapped, err := model.OIDCValidateActivate(pollToken, binding) // config edited mid-flow -> \"changed during validation\"\n// after\n// restart validation against the new config\nstart, _ := model.OIDCValidateStart(redirectURL)\n// poll then activate with the new transaction","handlingStrategy":"try-catch","validationCode":"// compare config version before activating\nif txn.ConfigVersion != model.OIDCConfigurationVersion() { warnConfigChanged(); restartValidation() }","typeGuard":null,"tryCatchPattern":"ok, changed, err := model.OIDCValidateActivate(pollToken, binding)\nif err != nil && strings.Contains(err.Error(), \"changed during validation\") {\n    // settings were edited mid-flow: restart validation against current config\n    return restartOIDCValidation()\n}","preventionTips":["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"],"tags":["oidc","config","concurrency","optimistic-locking"],"backgroundTag":"conflicting-config-options","analyzedSha":"9f775e8a12daef8255556097396f9b2739078892","analyzedAt":"2026-09-19T03:17:15.984Z","contentChangedAt":"2026-09-19T03:17:15.984Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}