siyuan-note/siyuan · error
cannot replay block swap across encrypted notebook…
Error message
cannot replay block swap across encrypted notebook boundaries
What it means
During block swap replay (undo/redo), the kernel re-collects the trees touched by the stored fragments and re-verifies that every tree's notebook is on the same crypto boundary as the first one. This error means the replay state now spans notebooks with incompatible encryption boundaries — typically because a block or tree was moved to a different notebook between the original swap and the replay.
Solutions
- Restore the involved blocks to their original notebooks, then retry undo/redo
- If the new location is intended, discard the undo history for that swap instead of replaying it
- Align notebook encryption settings across clients and re-sync
Defensive patterns
Strategy: try-catch
Validate before calling
const boxes = touchedTrees.map(t => t.box);
if (new Set(boxes).size > 1 && !sameCryptoBoundary(boxes)) throw new Error('replay would cross encrypted notebook boundary'); Try / catch
try { await replay(tx); } catch (e) {
if (e.message.includes('cannot replay block swap across encrypted notebook boundaries')) { /* drop undo entry or restore notebooks first */ }
} Prevention
- Avoid moving swap-involved blocks between differently-encrypted notebooks while undo entries are pending
- Keep notebook encryption uniform across synced clients
When it happens
Trigger: Undoing/redoing a block swap after one of the involved trees was moved to a notebook with a different crypto boundary; replaying synced state where notebooks differ in encryption across clients.
Common situations: Moving a swapped block to another notebook, then pressing undo; mixing encrypted and plain notebooks in a synced workspace; restoring a partial snapshot.
Understand the failure class
Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.
Related errors
- block swap undo state is unavailable
- cannot swap blocks across encrypted notebook boundaries
- CLI does not support encrypted notebook
- Conf.Language(314)
- Conf.Language(314)
AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19).
Data as JSON: /api/errors/3c74af731a26b3c8.
Report an issue: GitHub.
Appendix: source
Thrown at kernel/model/transaction_block_swap.go:210
func (tx *Transaction) replayBlockSwap(operation *Operation) error {
state := operation.blockSwapState
from, to := state.before, state.after
if operation.blockSwapUndo {
from, to = to, from
}
trees := map[string]*parse.Tree{}
var orderedTrees []*parse.Tree
for _, rootID := range state.rootIDs {
tree, err := tx.loadTree(rootID)
if err != nil {
return err
}
trees[rootID] = tree
orderedTrees = append(orderedTrees, tree)
}
for _, tree := range orderedTrees {
if !IsSameCryptoBoundary(orderedTrees[0].Box, tree.Box) {
return errors.New("cannot replay block swap across encrypted notebook boundaries")
}
}
tx.saveBlockSwapOriginalTrees(orderedTrees)
if err := restoreBlockSwapFragments(from, to, trees); err != nil {
return err
}
tx.finishBlockSwap(from, to, orderedTrees)
operation.RetData = state.rootIDs
return nil
}
func restoreBlockSwapFragments(from, to []blockSwapFragment, trees map[string]*parse.Tree) error {
removing := map[string]bool{}
for _, fragment := range from {
tree := trees[fragment.rootID]
if tree == nil || tree.Box != fragment.boxID {
return errors.New("block swap notebook has changed")
}View on GitHub (pinned to 9f775e8a12)