{"record":{"id":"97f1fcdf43e84668","repo":"siyuan-note/siyuan","slug":"database-history-id-does-not-match-its-filename","errorCode":null,"errorMessage":"database history ID does not match its filename","messagePattern":"database history ID does not match its filename","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/attribute_view_block_history.go","lineNumber":43,"sourceCode":"\t\treturn nil, err\n\t}\n\tif boxID != \"\" {\n\t\tif !util.IsCiphertext(data) {\n\t\t\treturn nil, errors.New(\"encrypted database history is plaintext\")\n\t\t}\n\t\tdata, err = av.DecryptAVData(boxID, avID, data)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t} else if util.IsCiphertext(data) {\n\t\treturn nil, errors.New(\"encrypted database history has no notebook context\")\n\t}\n\tview, err := av.ParseAttributeViewData(avID, data)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif view.ID != avID {\n\t\treturn nil, errors.New(\"database history ID does not match its filename\")\n\t}\n\tfor _, kv := range view.KeyValues {\n\t\tif kv == nil || kv.Key == nil {\n\t\t\treturn nil, errors.New(\"database history contains an invalid field\")\n\t\t}\n\t\tfor _, value := range kv.Values {\n\t\t\tif value == nil {\n\t\t\t\treturn nil, errors.New(\"database history contains an invalid value\")\n\t\t\t}\n\t\t}\n\t}\n\tif view.GetBlockKeyValues() == nil {\n\t\treturn nil, errors.New(\"database history has no primary field\")\n\t}\n\tfor _, layout := range view.Views {\n\t\tif layout == nil {\n\t\t\treturn nil, errors.New(\"database history contains an invalid view\")\n\t\t}","sourceCodeStart":25,"sourceCodeEnd":61,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/model/attribute_view_block_history.go#L25-L61","documentation":"After parsing a database history snapshot, the embedded attribute view ID inside the data must equal the avID derived from the history filename. A mismatch means the file does not belong to the database named by its path — usually a misnamed, copied, or mismatched history artifact — and restoring it would write foreign data into the wrong attribute view.","triggerScenarios":"restoreAttributeView/backupBoundAttributeViewHistory where view.ID != avID, e.g. a history file renamed to another attribute view's filename, history directories merged between databases, or a bug copying history artifacts under the wrong name.","commonSituations":"Manual file management of the history folder; backup-restore tooling that renames files; comparing/restoring across workspaces with divergent databases.","solutions":["Locate the history file whose embedded ID matches the target avID and restore that one instead","Rename nothing blindly: inspect the parsed view ID first and restore from the correct database's history list","Regenerate a fresh history entry of the current database if no matching snapshot exists","Report the mismatch if it arose from the built-in history writer (a naming bug)"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"const parsed = parseAVData(data);\nif (parsed.id !== avIDFromFilename(filename)) {\n  throw new Error('history file does not belong to ' + avID);\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never rename history files manually; let the history writer name them","Restore only from the history list the app generated for that database","Avoid merging history folders of different databases","Verify avID matches before programmatic history restore"],"tags":["database","history","id-mismatch","validation"],"backgroundTag":"checksum-mismatch","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"}