siyuan-note/siyuan · error
database binding [ ] already exists
Error message
database binding [%s] already exists
What it means
restoreDeletedAttributeViewBlocks is the undo operation (inverse of insertAttrViewBlock) that re-inserts database rows deleted in the same transaction and re-binds them to their document blocks. Before replaying, it verifies that no live row in the database is already bound to each block ID (GetBlockValueByBoundID(id) == nil). If a row is already bound to that block, re-inserting would create a duplicate binding, so the undo fails with the block ID.
Solutions
- Delete the row currently bound to that block ID in the database so the undo can restore the original row, then retry the undo
- Undo again from an earlier point in the history panel instead of transactional undo
- Verify the existing binding points to the intended row; if it is already correct, no undo of the deletion is needed for that row — remove its entry from the undo operation
- Check for duplicate bindings via the database UI and clean up stale rows before retrying
Defensive patterns
Strategy: try-catch
Validate before calling
// Go: before undoing a row deletion, check the binding is free
if current.GetBlockValueByBoundID(blockID) != nil {
// a row is already bound; resolve before undo
} Type guard
if current.GetBlockValueByBoundID(id) == nil {
// safe to re-insert and bind
} Try / catch
err := tx.restoreDeletedAttributeViewBlocks(op)
if err != nil && strings.Contains(err.Error(), "already exists") {
// remove the conflicting row or skip this Src entry, then retry
} Prevention
- Undo deletions in order (blocks first, rows second)
- Avoid re-adding blocks to the database between delete and undo
- Prevent concurrent undo from multiple windows/sync
- Verify bindings before manual row re-creation
When it happens
Trigger: Undoing a transaction that deleted attribute-view rows, where a row bound to the same document block was meanwhile re-created in the same database (e.g. the user re-added the block to the database, or a prior undo/redo partially restored bindings), so current.GetBlockValueByBoundID(id) returns non-nil.
Common situations: Redo/undo cycles interleaved with manual re-adds of the block to the database; repeated undo invocations after a partially applied undo; concurrent clients (sync or multiple windows) re-creating rows for the same block.
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
- database block [ ] is already bound
- database entry [ ] has a different binding
- restored database binding
- restored database entry
- attribute view not found
AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19).
Data as JSON: /api/errors/3127e258a41bd7ed.
Report an issue: GitHub.
Appendix: source
Thrown at kernel/model/attribute_view_block_undo.go:120
func (tx *Transaction) restoreDeletedAttributeViewBlocks(op *Operation) error {
state := op.attributeViewFields
if err := tx.rememberAttributeViewMutationTree(state.blockID); err != nil {
return err
}
for _, src := range op.Srcs {
id, _ := src["id"].(string)
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 errView on GitHub (pinned to 9f775e8a12)