{"record":{"id":"9a0d255c3bdecb81","repo":"siyuan-note/siyuan","slug":"encrypted-notebook-document-history-is-plaintext","errorCode":null,"errorMessage":"encrypted notebook document history is plaintext [%s]","messagePattern":"encrypted notebook document history is plaintext \\[(.+?)\\]","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/history.go","lineNumber":204,"sourceCode":"\t\thistBoxID := pathParts[1]\n\t\tif !IsEncryptedBox(histBoxID) {\n\t\t\terr = fmt.Errorf(\"encrypted document history has no matching notebook [%s]\", histBoxID)\n\t\t\treturn\n\t\t}\n\t\tHoldBoxReadLock(histBoxID)\n\t\tdefer ReleaseBoxReadLock(histBoxID)\n\t\tdek, dekErr := GetDEKIfUnlocked(histBoxID)\n\t\tif dekErr != nil {\n\t\t\terr = errors.New(Conf.Language(314))\n\t\t\treturn\n\t\t}\n\t\tdata, err = DecryptFile(histBoxID, pathParts[2], dek, data)\n\t\tif err != nil {\n\t\t\tlogging.LogErrorf(\"decrypt history [%s] failed: %s\", historyPath, err)\n\t\t\treturn\n\t\t}\n\t} else if len(pathParts) >= 2 && IsEncryptedBox(pathParts[1]) {\n\t\terr = fmt.Errorf(\"encrypted notebook document history is plaintext [%s]\", pathParts[1])\n\t\treturn\n\t}\n\tisLargeDoc = 1024*1024*1 <= len(data)\n\n\tluteEngine := NewLute()\n\tif err = treenode.CheckSpecJSON(data); nil != err {\n\t\treturn\n\t}\n\thistoryTree, err := dataparser.ParseJSONWithoutFix(data, luteEngine.ParseOptions)\n\tif err != nil {\n\t\tlogging.LogErrorf(\"parse tree from file [%s] failed: %s\", historyPath, err)\n\t\treturn\n\t}\n\tid = historyTree.Root.ID\n\trootID = historyTree.Root.ID\n\tif ciphertext && rootID+\".sy\" != filepath.Base(historyPath) {\n\t\treturn \"\", \"\", \"\", false, errors.New(\"encrypted document history root ID does not match its filename\")\n\t}","sourceCodeStart":186,"sourceCodeEnd":222,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/8641553a1f07374001902d3ce773285db1292b2d/kernel/model/history.go#L186-L222","documentation":"For an encrypted notebook the kernel requires history files to be ciphertext; a plaintext file under an encrypted notebook's history is an integrity violation (e.g. data written before encryption, tampering, or a broken sync), so the reader refuses with 'encrypted notebook document history is plaintext [%s]' rather than silently returning unauthenticated content.","triggerScenarios":"pathParts[1] is an encrypted notebook ID but util.IsCiphertext(data) is false — the history blob for that notebook is plaintext.","commonSituations":"History generated by an older kernel version before encryption was applied; data corrupted by third-party sync tools writing plaintext snapshots; manual edits under history/; mixing workspaces where the notebook was encrypted only later (old plaintext history remains).","solutions":["Remove or ignore the stale plaintext history entries generated before encryption, then regenerate history by editing documents in the encrypted notebook","Verify sync integrity — re-sync the history data from a trusted source","Do not manually edit files under data/history/; restore the history directory from backup if it was modified"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  return await fetchPost('/api/history/getDocHistoryContent', {historyPath});\n} catch (e) {\n  if (String(e.msg).includes('history is plaintext')) {\n    // mark the entry as corrupt/legacy and exclude it from the history list\n    return {content: null, corrupt: true};\n  } else throw e;\n}","preventionTips":["Never edit or inject files under data/history/","Use SiYuan's own sync; third-party sync of history can produce inconsistent snapshots","After enabling notebook encryption, treat pre-encryption plaintext history as legacy and regenerate it"],"tags":["history","encrypted-notebook","integrity"],"backgroundTag":"checksum-mismatch","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"}