{"record":{"id":"9d4068f3f165306c","repo":"siyuan-note/siyuan","slug":"database-s-w","errorCode":null,"errorMessage":"database [%s]: %w","messagePattern":"database \\[(.+?)\\]: %w","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/attribute_view_fields.go","lineNumber":271,"sourceCode":"\t\t\t}\n\t\t}\n\t\t// 恢复双向定义时，另一端的单向值必须仍与删除时一致。\n\t\tfor keyID, expected := range state.relationValues[id] {\n\t\t\tkv, keyErr := current.GetKeyValues(keyID)\n\t\t\tif keyErr != nil {\n\t\t\t\treturn keyErr\n\t\t\t}\n\t\t\tif !reflect.DeepEqual(attributeViewRelationValueIDs(kv.Values), expected) {\n\t\t\t\treturn fmt.Errorf(\"database back relation values [%s] changed after field deletion\", keyID)\n\t\t\t}\n\t\t}\n\t\tdata, err := attributeViewFieldJSON(current)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tpatched, _, err := state.changes[id].apply(data, true, op.attributeViewFieldUndo)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"database [%s]: %w\", id, err)\n\t\t}\n\t\tencoded, err := json.Marshal(patched)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\trestored := &av.AttributeView{}\n\t\tif err = json.Unmarshal(encoded, restored); err != nil {\n\t\t\treturn err\n\t\t}\n\t\tfor _, kv := range restored.KeyValues {\n\t\t\tif _, keyErr := current.GetKey(kv.Key.ID); keyErr == nil {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tfor _, value := range kv.Values {\n\t\t\t\tif restored.GetBlockValue(value.BlockID) == nil {\n\t\t\t\t\treturn fmt.Errorf(\"database entry [%s] was removed after the field\", value.BlockID)\n\t\t\t\t}\n\t\t\t}","sourceCodeStart":253,"sourceCodeEnd":289,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/model/attribute_view_fields.go#L253-L289","documentation":"replayAttributeViewFields serializes the current database, applies the recorded JSON patch (state.changes[id].apply), and wraps any patch-application failure with 'database [<avID>]: <cause>'. This means the recorded before/after diff for that database can no longer be applied cleanly to the live JSON — the underlying document structure drifted from what was captured.","triggerScenarios":"Undo/redo replay of add/remove-column, update-column-options, restore-deleted-blocks, sort-item, or item-configuration operations when the live attribute-view JSON no longer matches the patch base (fields, views, filters, or values changed by sync, concurrent edits, or format upgrades).","commonSituations":"Workspace synced between versions with changed database JSON schema; the database was edited by another client while undo was pending; a plugin wrote the .av JSON directly bypassing transactions.","solutions":["Re-sync or reload the workspace so the database matches the version the snapshot was taken from","Drop the conflicting undo/redo entry and manually re-apply the intended field change","Upgrade/downgrade consistently across all devices so the database JSON format matches what the kernel that recorded the patch expects"],"exampleFix":"// before\npatched, _, err := state.changes[id].apply(data, true, undo)\nif err != nil { panic(err) }\n// after\npatched, _, err := state.changes[id].apply(data, true, undo)\nif err != nil {\n    return fmt.Errorf(\"database [%s]: %w\", id, err) // surfaced: refresh or skip replay\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"if err := tx.replayAttributeViewFields(op); err != nil {\n    var wrapped = err.Error()\n    if strings.Contains(wrapped, \"database [\") {\n    // patch no longer applies: log avID, refresh or skip the undo step\n    return nil\n}\nreturn err","preventionTips":["Do not write .av JSON files directly outside transactions","Keep all clients on the same kernel version for database JSON formats","Re-sync before replaying old undo entries"],"tags":["database","attribute-view","json-patch","undo-redo"],"backgroundTag":"json-patch-apply-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"}