siyuan-note/siyuan · error

template document tree plan contains an unsupported parent o

Error message

template document tree plan contains an unsupported parent operation

What it means

Every parent DoOperation must use an action from the inverseActions allowlist and have an empty RootID. This error means the forward operation's action cannot be inverted by the plan machinery (e.g. moveBlock, appendBlock) or it carries a RootID, which would conflict with the reserved child-document operations the plan appends (restoreCreatedDoc/removeCreatedDoc).

Source

Thrown at kernel/model/template_doc_tree.go:554

	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 = true
		}
		key := inverseAction + "\x00" + operation.ID
		if 1 > undoOperations[key] {
			return errors.New("template document tree plan parent operations are not reversible")
		}
		undoOperations[key]--
	}
	if !hasContentMutation {
		return errors.New("template document tree plan requires a parent content operation")
	}
	for _, count := range undoOperations {
		if 0 != count {
			return errors.New("template document tree plan parent operations are not reversible")
		}
	}

View on GitHub (pinned to 8641553a1f)

Solutions

  1. Use only insert, delete, update, foldHeading, unfoldHeading, or setAttrs for parent DoOperations
  2. Ensure every parent operation has RootID set to ""
  3. Move unrelated or unsupported edits into separate normal transactions
  4. Update the kernel if the needed action should be supported; check the inverseActions map in validateTemplateDocTreeParentOperations

Example fix

// before
doOps := []*Operation{{Action: "appendBlock", RootID: rootID, ID: blkID}}
// after
doOps := []*Operation{{Action: "insert", ID: blkID, ParentID: parentID}} // supported action, empty RootID
Defensive patterns

Strategy: validation

Validate before calling

supported := map[string]bool{"insert":true,"delete":true,"update":true,"foldHeading":true,"unfoldHeading":true,"setAttrs":true}; for _, op := range tx.DoOperations { if !supported[op.Action] || op.RootID != "" { reject before submit } }

Try / catch

if err != nil && strings.Contains(err.Error(), "unsupported parent operation") { split out non-allowlisted actions into separate normal transactions and resubmit }

Prevention

When it happens

Trigger: Submitting a plan transaction containing unsupported parent actions; setting RootID on parent operations; forwarding user edits recorded by other kernel features (which use RootID) into a plan transaction.

Common situations: Bulk-edit automation that batches mixed action types into one transaction; porting code from a kernel version where additional actions existed; misunderstanding that RootID here must stay empty for parent ops.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


AI-assisted analysis of siyuan-note/siyuan@8641553a1f (2026-09-11). Data as JSON: /api/errors/ce030393d08256c8. Report an issue: GitHub.