{"record":{"id":"3dce0f16fb0b6d37","repo":"siyuan-note/siyuan","slug":"conf-language-323","errorCode":null,"errorMessage":"Conf.Language(323)","messagePattern":"Conf\\.Language\\(323\\)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"kernel/model/crypto.go","lineNumber":1108,"sourceCode":"\tnotebookCryptoMu.Lock()\n\tdefer notebookCryptoMu.Unlock()\n\n\t// 检查是否还有加密笔记本（含 conf 损坏但存在备份的）\n\tids, listErr := listAllEncryptedBoxIDs()\n\tif listErr != nil {\n\t\treturn fmt.Errorf(\"list encrypted notebooks failed: %w\", listErr)\n\t}\n\tif len(ids) > 0 {\n\t\treturn errors.New(\"cannot disable encrypted notebook feature while encrypted notebooks exist, remove them first\")\n\t}\n\t// 检查历史目录中是否存在已删除加密笔记本的历史快照：其恢复仍依赖当前 MasterSalt/KEKVerifier，\n\t// 删除备份前必须先清除这些历史（详见设计 §19）\n\thasHistory, historyErr := scanEncryptedNotebookHistory()\n\tif historyErr != nil {\n\t\treturn fmt.Errorf(\"check encrypted notebook history failed: %w\", historyErr)\n\t}\n\tif hasHistory {\n\t\treturn errors.New(Conf.Language(323))\n\t}\n\n\tConf.m.Lock()\n\tConf.NotebookCrypto.Enabled = false\n\tConf.NotebookCrypto.MasterSalt = nil\n\tConf.NotebookCrypto.KEKVerifier = nil\n\tConf.NotebookCrypto.VerifierNonce = nil\n\tConf.m.Unlock()\n\n\tConf.Save()\n\tremoveNotebookCryptoBackup() // 禁用时清理备份，避免残留旧密钥材料\n\tIncSync()\n\treturn nil\n}\n\n// restoreNotebookCryptoConfigFromBackup 把备份里的 NotebookCrypto 配置装回本机 conf.json（不需主密码）。\n// 用于数据同步/导入 Data.zip 后：备份文件随 DataDir 到达新设备，但本机 conf.json 的 NotebookCrypto 还是空的。\n// 此时把 salt/verifier/KDFParams 装回并置 Enabled=true，让 UI 显示\"已启用\"，笔记本显示为锁定（解锁仍需主密码）。","sourceCodeStart":1090,"sourceCodeEnd":1126,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/8641553a1f07374001902d3ce773285db1292b2d/kernel/model/crypto.go#L1090-L1126","documentation":"DisableEncryptedNotebook refuses to disable the encrypted-notebook feature when the history directory still contains snapshots of deleted encrypted notebooks (Conf.Language(323)). Those snapshots can only be recovered with the current MasterSalt/KEKVerifier, so wiping the key material first would make the history unrecoverable. The kernel deliberately aborts and asks the user to clear that history first.","triggerScenarios":"Calling POST /api/notebook/disableEncryptedNotebooks (kernel handler disableEncryptedNotebooks -> DisableEncryptedNotebook) while scanEncryptedNotebookHistory() finds history snapshots belonging to previously deleted encrypted notebooks.","commonSituations":"A user deleted encrypted notebooks in the past (leaving stale entries under the history directory), then tries to switch the encrypted-notebook feature off from settings; or after restoring/syncing data that still carries old encrypted-notebook history.","solutions":["Open the history panel and permanently clear the remaining encrypted-notebook history snapshots (Data > history), then retry disabling the feature","Manually remove the orphaned encrypted-notebook snapshots from the workspace history directory, then call the API again","If the history is still needed, do not disable the feature; decrypt/export the notebooks first, clear history, then disable"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Go (kernel client script): refuse to disable while encrypted-notebook history remains\nif has, _ := model.ScanEncryptedNotebookHistoryForCheck(); has {\n    return errors.New(\"clear encrypted-notebook history snapshots before disabling the feature\")\n}\n_ = model.DisableEncryptedNotebook()","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Before disabling the feature, open the history panel and purge snapshots of deleted encrypted notebooks","Treat the guard message as a required cleanup step, not a bug","Keep backups of the workspace before toggling encryption features"],"tags":["go","kernel","encryption","notebook-history","guard-error"],"backgroundTag":"invalid-state-transition","analyzedSha":"8641553a1f07374001902d3ce773285db1292b2d","analyzedAt":"2026-09-11T16:08:28.414Z","contentChangedAt":"2026-09-11T16:08:28.414Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}