siyuan-note/siyuan · error
template document tree plan contains an invalid parent undo
Error message
template document tree plan contains an invalid parent undo operation
What it means
validateTemplateDocTreeParentOperations pre-checks the transaction before a plan is attached. Every UndoOperation must be non-nil and carry a non-empty ID. This error means an undo operation is nil or missing its block ID, so it cannot be paired with a forward operation for reversibility.
Source
Thrown at kernel/model/template_doc_tree.go:539
templateDocTreeRootID: plan.rootID,
})
}
return true, nil
}
func validateTemplateDocTreeParentOperations(transaction *Transaction) error {
inverseActions := map[string]string{
"insert": "delete",
"delete": "insert",
"update": "update",
"foldHeading": "unfoldHeading",
"unfoldHeading": "foldHeading",
"setAttrs": "setAttrs",
}
undoOperations := map[string]int{}
for _, operation := range transaction.UndoOperations {
if nil == operation || "" == operation.ID {
return errors.New("template document tree plan contains an invalid parent undo operation")
}
if _, supported := inverseActions[operation.Action]; !supported || "" != operation.RootID {
return errors.New("template document tree plan contains an unsupported parent undo operation")
}
undoOperations[operation.Action+"\x00"+operation.ID]++
}
hasContentMutation := false
for _, operation := range transaction.DoOperations {
if nil == operation || "" == operation.ID {
return errors.New("template document tree plan contains an invalid parent operation")
}
inverseAction, supported := inverseActions[operation.Action]
if !supported || "" != operation.RootID {
return errors.New("template document tree plan contains an unsupported parent operation")
}
if "insert" == operation.Action || "delete" == operation.Action || "update" == operation.Action {
hasContentMutation = trueView on GitHub (pinned to 8641553a1f)
Solutions
- Populate Operation.ID for every entry in UndoOperations (the block ID being reverted)
- Remove nil entries from the UndoOperations slice before calling performTransactions
- Build the transaction via the kernel's normal operation pipeline so IDs are assigned consistently
- Validate the transaction client-side (non-nil ops, non-empty IDs) before submission
Example fix
// before
undoOps := []*Operation{{Action: "delete"}} // ID missing
// after
undoOps := []*Operation{{Action: "delete", ID: parentBlockID}} Defensive patterns
Strategy: validation
Validate before calling
for i, op := range tx.UndoOperations { if op == nil || op.ID == "" { return fmt.Errorf("undo operation %d missing ID", i) } } Type guard
func validUndoOps(ops []*Operation) bool { for _, op := range ops { if op == nil || op.ID == "" { return false } }; return len(ops) > 0 } Try / catch
if err != nil && strings.Contains(err.Error(), "invalid parent undo operation") { fix the transaction builder to assign IDs, then resubmit } Prevention
- Always set Operation.ID on undo operations
- Filter nils from the UndoOperations slice before submission
- Build transactions with the standard kernel pipeline, not by hand
- Unit-test transaction fixtures for nil/empty IDs
When it happens
Trigger: Constructing a Transaction for a template plan whose UndoOperations slice contains a nil entry or an Operation with ID ""; hand-assembled transactions in scripts/tests omitting IDs; upstream code that builds undo ops without setting IDs.
Common situations: Plugin or integration code manually building plan transactions instead of using the standard transaction builder; a serialization bug dropping empty IDs; tests constructing minimal fixtures.
Understand the failure class
Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.
Related errors
- template document tree plan contains an unsupported parent u
- template document tree plan contains an invalid parent opera
- template document tree plan contains an unsupported parent o
- template document tree plan parent operations are not revers
- wrong layout type
AI-assisted analysis of siyuan-note/siyuan@8641553a1f (2026-09-11).
Data as JSON: /api/errors/df4635a7846f0417.
Report an issue: GitHub.