{"record":{"id":"2a44507df85aea18","repo":"siyuan-note/siyuan","slug":"database-history-contains-an-invalid-field","errorCode":null,"errorMessage":"database history contains an invalid field","messagePattern":"database history contains an invalid field","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/attribute_view_block_history.go","lineNumber":47,"sourceCode":"\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}\n\t\tfor _, group := range layout.Groups {\n\t\t\tif group == nil {\n\t\t\t\treturn nil, errors.New(\"database history contains an invalid group\")\n\t\t\t}","sourceCodeStart":29,"sourceCodeEnd":65,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/model/attribute_view_block_history.go#L29-L65","documentation":"Structural validation of a parsed database history snapshot failed: a KeyValues entry or its Key is nil. The engine validates every history attribute view before use so restores never inject malformed fields into a live database; a nil key indicates a truncated or hand-edited history file.","triggerScenarios":"readBoundAttributeViewHistory iterating view.KeyValues where a kv pointer is nil or kv.Key is nil — produced by truncated/corrupt history files, partial writes, or files edited by external tools.","commonSituations":"Disk-full or interrupted writes when the snapshot was taken; merging history folders across workspaces; third-party scripts rewriting history JSON.","solutions":["Discard the corrupt history entry and choose another snapshot from the history list","Restore the history file from backup","Rebuild history by making a new change to the database to generate a fresh snapshot","If corruption recurs, check storage integrity (disk, sync target) for the history directory"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"function isValidHistoryView(view) {\n  return view.keyValues.every(kv => kv && kv.key);\n}","typeGuard":"const hasValidKeys = (view) =>\n  Array.isArray(view.keyValues) && view.keyValues.every(kv => kv && kv.key);","tryCatchPattern":null,"preventionTips":["Do not hand-edit history files","Keep the history directory on reliable storage; watch for disk-full events","Take fresh snapshots after suspected interrupted writes","Validate backups by restoring them periodically"],"tags":["database","history","schema","corruption"],"backgroundTag":"schema-validation-failed","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"}