{"record":{"id":"56b7ce9c911ef6b7","repo":"siyuan-note/siyuan","slug":"oidc-validation-configuration-is-missing","errorCode":null,"errorMessage":"OIDC validation configuration is missing","messagePattern":"OIDC validation configuration is missing","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/oidc.go","lineNumber":836,"sourceCode":"\tcopy := *transaction\n\treturn &copy, true\n}\n\nfunc activateOIDCValidation(pollToken, binding string) (activated bool, err error) {\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.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 == \"\" ||","sourceCodeStart":818,"sourceCodeEnd":854,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/251596fc0de2f9528c00c224252fd073a99973f4/kernel/model/oidc.go#L818-L854","documentation":"The validate-flow transaction reached activation but transaction.Config is nil. The config snapshot is captured at validation start and is only cleared on a successful activation (set to nil) or on a failed completion - so nil here means the transaction is in an unexpected state, typically a double-activation attempt.","triggerScenarios":"Activating a transaction whose Config was already nilled by a prior activation that did not flip Activated, or whose completion failed and cleared Config.","commonSituations":"Client retries activation after an earlier call already consumed the config; activation racing the completion cleanup path.","solutions":["Do not re-activate - inspect the result of the first activation call.","If the first activation errored, re-run validation from the start.","Treat an already-activated transaction as success: activateOIDCValidation returns (false, nil) when Activated is already true."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"// Distinguish 'already activated' (ok) from a real state error.\nactivated, err := activateOIDCValidation(pollToken, binding)\nif err != nil && strings.Contains(err.Error(), \"configuration is missing\") {\n    // most likely already activated; re-poll to confirm current state\n    if tx, ok := pollOIDCTransaction(pollToken, binding); ok && tx.Activated {\n        return nil // already activated, nothing to do\n    }\n}","preventionTips":["Do not call validateActivate twice for the same poll token.","Inspect the activation result before retrying.","Re-run validation from the start if the first activation genuinely errored."],"tags":["oidc","validation","state-machine"],"backgroundTag":null,"analyzedSha":"251596fc0de2f9528c00c224252fd073a99973f4","analyzedAt":"2026-08-12T21:18:37.123Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}