siyuan-note/siyuan · error
restored database entry
Error message
restored database entry [%s] is missing
What it means
During undo of a transaction that inserted attribute-view (database) blocks, restoreDeletedAttributeViewBlocks re-adds previously deleted rows into the attribute view and then validates that the specific item (row) being restored exists in the restored collection. If GetBlockValue(itemID) returns nil — i.e. no block value with that item ID exists after restore — it aborts the transaction with this error. This is an internal consistency guard: the undo log references a database row that the restore operation could not actually materialize.
Solutions
- Verify the target database still exists and the row with the given itemID is present before triggering undo
- Refresh/reload the document so the attribute-view index matches disk, then retry the undo
- Check for sync or concurrent-edit conflicts that removed the row and resolve conflicts first
- If reproducible, clear the undo stack for the affected document (re-open the document) and report the mismatch
Defensive patterns
Strategy: validation
Validate before calling
av := getAttributeView(avID)
item := av.GetBlockValue(itemID)
if item == nil || item.Block == nil { return fmt.Errorf("item %s no longer exists; undo unavailable", itemID) } Type guard
func canUndoAttrViewBlock(av *av.AttributeView, itemID string) bool {
v := av.GetBlockValue(itemID)
return v != nil && v.Block != nil
} Try / catch
if err := doUndo(tx); err != nil {
if strings.Contains(err.Error(), "restored database entry") {
refreshDocument(); return // undo stack stale, reload instead
}
return err
} Prevention
- Do not permanently delete database rows while undoable operations referencing them are in the stack
- Resolve sync conflicts before performing undo
- Re-open documents whose databases were heavily edited so the undo stack resets to consistent state
When it happens
Trigger: Undoing a doInsertAttrViewBlock operation when the transaction's src.ID (itemID) does not match any row restored into the target attribute view; e.g. the database was modified, the row was permanently deleted, or the AV was unlinked between the original operation and the undo.
Common situations: Undo stack references stale data after the database table was deleted or re-created; concurrent edits removed the row; a corrupted or partially synced .sy file leaves the AV index without the expected item; undoing across a sync that replaced the document's databases.
Understand the failure class
Background: Record Not Found Errors: "not found", RecordNotFound, and "was not found" — what they mean and how to fix them — this error's family across 28 libraries.
Related errors
- database back relation field
- database binding [ ] already exists
- restored database binding
- attribute view not found
- cannot remove primary key field
AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19).
Data as JSON: /api/errors/f2b77a15f3e4bfa0.
Report an issue: GitHub.
Appendix: source
Thrown at kernel/model/attribute_view_block_undo.go:150
}
if err := tx.replayAttributeViewFields(op); err != nil {
return err
}
restored, err := tx.readAttributeViewForMutation(op.AvID, state.blockID, state.boxID)
if err != nil {
return err
}
var itemIDs []string
for _, src := range op.Srcs {
id, _ := src["id"].(string)
node, tree, err := getNodeByBlockID(tx, id)
if err != nil {
return err
}
itemID, _ := src["itemID"].(string)
primary := restored.GetBlockValue(itemID)
if primary == nil || primary.Block == nil {
return fmt.Errorf("restored database entry [%s] is missing", itemID)
}
attrs := parse.IAL2Map(node.KramdownIAL)
ids := strings.Split(attrs[av.NodeAttrNameAvs], ",")
if !slices.Contains(ids, op.AvID) {
ids = append(ids, op.AvID)
}
attrs[av.NodeAttrNameAvs] = strings.Trim(strings.Join(ids, ","), ",")
attrs[av.NodeAttrViewNames] = getAvNames(attrs[av.NodeAttrNameAvs])
if primary.Block.RefSubtype == "s" {
attrs[av.NodeAttrViewStaticText+"-"+op.AvID] = primary.Block.Content
}
if err = setNodeAttrsWithTx(tx, node, tree, attrs); err != nil {
return err
}
itemIDs = append(itemIDs, itemID)
}
op.RetData = &insertAttrViewBlockResult{InsertedItemIDs: itemIDs}
return nilView on GitHub (pinned to 9f775e8a12)