{"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":"warning","filePath":"kernel/model/oidc.go","lineNumber":841,"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":823,"sourceCodeEnd":859,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/251596fc0de2f9528c00c224252fd073a99973f4/kernel/model/oidc.go#L823-L859","documentation":"Conf.CompareAndSetOIDC(ConfigVersion, Config) returned swapped == false during activation: another OIDC config write landed between validation start and activation. The candidate config is discarded and the transaction is deleted as stale.","triggerScenarios":"A second admin (or automation) saved OIDC settings while a validation activation is in flight; rapid config churn racing with activation.","commonSituations":"Two admins validating/editing OIDC at once; config pushed by tooling that races the manual validate flow.","solutions":["Re-run validation start with the latest intended config.","Ensure only one admin/process edits OIDC config at a time.","Treat the prior validation result as stale and discard it."],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"// CAS lost: re-run validation start with the latest config.\nif _, err := activateOIDCValidation(pollToken, binding); err != nil && strings.Contains(err.Error(), \"configuration changed during validation\") {\n    restartValidationFlow(c)\n}","preventionTips":["Ensure only one admin/process edits OIDC config at a time.","Treat the validation result as stale once config changes mid-flight.","Re-validate against the current config before activating."],"tags":["oidc","concurrency","configuration","race-condition"],"backgroundTag":null,"analyzedSha":"251596fc0de2f9528c00c224252fd073a99973f4","analyzedAt":"2026-08-12T21:18:37.123Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}