siyuan-note/siyuan · error
restored database binding
Error message
restored database binding [%s] is missing
What it means
As part of the undo for deleted attribute-view rows, each restored row must be re-bound to an existing document block. The code looks up the block by ID (getNodeByBlockID(tx, id)); if the node no longer exists in any open tree, the binding target is gone and the row cannot be re-attached, so the undo aborts naming the missing block ID.
Solutions
- Undo the block deletion first (or restore the document) so the block nodes exist, then undo the database-row deletion
- Re-create blocks with the same IDs is generally impossible — instead roll back via document history (RollbackDocHistory), which handles missing snapshots gracefully
- Skip/remove stale entries in the undo operation's Srcs whose blocks no longer exist, and re-create the rows manually
- Refresh/re-open the documents to ensure the trees are loaded, then retry the undo
Defensive patterns
Strategy: validation
Validate before calling
// Go: before undoing a row deletion, ensure the block still exists node, tree, err := getNodeByBlockID(tx, blockID) blockExists := err == nil && node != nil
Type guard
if node == nil {
return ErrBlockMissing
} Try / catch
err := tx.restoreDeletedAttributeViewBlocks(op)
if err != nil && strings.Contains(err.Error(), "is missing") {
// restore/undo the block deletion first, then retry
} Prevention
- Always undo block deletions before undoing database-row deletions
- Avoid deleting documents whose rows you plan to restore via undo
- Use document history rollback when blocks are already gone
- Keep undo operations atomic; do not clear undo stacks partially
When it happens
Trigger: Undoing deletion of attribute-view rows whose bound document blocks were deleted (in the same or a later transaction) and are no longer available — e.g. the deletion of the blocks was not undone first, the block IDs are stale, or the document containing them was removed.
Common situations: Undoing only the database-row deletion while the block deletion itself is gone from the undo stack (partial undo); blocks deleted in a separate earlier transaction; document deleted and rolled back differently; IDs from an out-of-date undo operation after sync.
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 binding [ ] already exists
- restored database entry
- attribute view not found
- cannot remove primary key field
- clone attribute view value
AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19).
Data as JSON: /api/errors/8e22dea887bc61c3.
Report an issue: GitHub.
Appendix: source
Thrown at kernel/model/attribute_view_block_undo.go:127
if err := tx.rememberAttributeViewMutationTree(id); err != nil {
return err
}
}
current, err := tx.readAttributeViewForMutation(op.AvID, state.blockID, state.boxID)
if err != nil {
return err
}
for _, src := range op.Srcs {
id, _ := src["id"].(string)
if current.GetBlockValueByBoundID(id) != nil {
return fmt.Errorf("database binding [%s] already exists", id)
}
node, tree, err := getNodeByBlockID(tx, id)
if err != nil {
return err
}
if node == nil {
return fmt.Errorf("restored database binding [%s] is missing", id)
}
if err = validateAttributeViewBinding(op.AvID, tree); err != nil {
return err
}
}
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 errView on GitHub (pinned to 9f775e8a12)