siyuan-note/siyuan · error
invalid database entry replay
Error message
invalid database entry replay
What it means
restoreAttributeViewItems re-inserts rows recorded in a deletion snapshot during undo replay. It first requires tx.isReplay to be true and op.AvID to match the snapshot's AvID (state.AvID); anything else — calling it outside replay, or an operation whose AvID was changed or detached from its snapshot — is rejected as 'invalid database entry replay' because the recorded rows cannot be safely restored into a different database or context.
Solutions
- Let the kernel capture the deletion snapshot automatically (do not hand-build insertAttrViewBlock inverses)
- Keep op.AvID identical to the snapshot's AvID throughout the transaction lifecycle
- Clear the corrupt undo entry (or rebuild the undo stack) and repeat the delete/undo cycle cleanly
Example fix
// before
op.AvID = otherAvID // retargeted inverse operation
// after
if op.AvID == snapshot.AvID && tx.isReplay {
return tx.restoreAttributeViewItems(op)
}
Defensive patterns
Strategy: try-catch
Validate before calling
if !tx.isReplay || op.attributeViewItems == nil || op.AvID != op.attributeViewItems.AvID {
return fmt.Errorf("skip entry restore: snapshot/operation mismatch")
} Type guard
func entrySnapshotValid(op *model.Operation) bool {
s := op.attributeViewItems
return s != nil && op.AvID == s.AvID
} Try / catch
if err := tx.restoreAttributeViewItems(op); err != nil {
if strings.Contains(err.Error(), "invalid database entry replay") {
// drop the stale inverse operation and rebuild the undo stack
return nil
}
return err
} Prevention
- Do not hand-construct insertAttrViewBlock inverses; rely on kernel snapshot capture
- Never retarget AvID on captured undo operations
- Keep undo history within a single workspace; clear it after major sync merges
When it happens
Trigger: doInsertAttrViewBlock replay where the operation's AvID was altered between capture and replay, the attributeViewItems snapshot is missing or belongs to another database, or restoreAttributeViewItems is invoked with tx.isReplay false (direct call instead of replay).
Common situations: A plugin manually composes insertAttrViewBlock undo operations without the kernel-managed snapshot; operations reordered/re-targeted by custom transaction code; undo stack entries from a different workspace or synced from another client with different database IDs.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- invalid database field replay
- database back relation values
- database entry [ ] changed since deletion was undone
- database entry [ ] has newer field values
- database entry [ ] was removed after the field
AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19).
Data as JSON: /api/errors/cea784f5ff7e5cb9.
Report an issue: GitHub.
Appendix: source
Thrown at kernel/model/attribute_view_items.go:285
for _, value := range kv.Values {
if !value.IsDetached && value.Block != nil {
blockIDs = append(blockIDs, value.Block.ID)
}
}
}
}
for _, id := range blockIDs {
if err := tx.rememberAttributeViewMutationTree(id); err != nil {
return err
}
}
return nil
}
func (tx *Transaction) restoreAttributeViewItems(op *Operation) error {
state := op.attributeViewItems
if !tx.isReplay || op.AvID != state.AvID {
return fmt.Errorf("invalid database entry replay")
}
current, err := tx.readAttributeViewItems(state)
if err != nil {
return err
}
for _, kv := range current.KeyValues {
for _, value := range kv.Values {
if slices.Contains(state.ItemIDs, value.BlockID) {
return fmt.Errorf("database entry [%s] already exists", value.BlockID)
}
}
}
if err = validateAttributeViewItemKeys(current, state); err != nil {
return err
}
for _, kv := range state.Keys {
for _, value := range kv.Values {
if value.Type != av.KeyTypeBlock || value.IsDetached || value.Block == nil {View on GitHub (pinned to 9f775e8a12)