siyuan-note/siyuan · error

the document used to render the template has changed

Error message

the document used to render the template has changed

What it means

After matching the plan to the transaction, the kernel reloads the template root document via LoadTreeByBlockID and compares its box, path, and HPath against the values recorded when the plan was rendered. Any difference (or a load error) means the root document was modified, moved, renamed, or deleted between rendering and applying, so the plan is stale.

Source

Thrown at kernel/model/template_doc_tree.go:494

	}

	planID := target.TemplateDocTreePlanID
	target.TemplateDocTreePlanID = ""
	value, loaded := templateDocTreePlans.LoadAndDelete(planID)
	if !loaded {
		return false, errors.New("template document tree plan is missing or has expired")
	}
	plan, ok := value.(*templateDocTreePlan)
	if !ok || plan.id != planID || time.Now().After(plan.expiresAt) {
		return false, errors.New("template document tree plan is invalid or has expired")
	}
	if !transactionTargetsTemplateRoot(target, plan.rootID, plan.boxID) {
		return false, errors.New("template document tree plan does not match the edited document")
	}
	rootTree, loadErr := LoadTreeByBlockID(plan.rootID)
	if nil != loadErr || nil == rootTree || rootTree.Box != plan.boxID || rootTree.Path != plan.rootPath ||
		rootTree.HPath != plan.rootHPath {
		return false, errors.New("the document used to render the template has changed")
	}
	target.templateDocTreeRootSnapshot = rootTree
	box := Conf.Box(plan.boxID)
	if nil == box {
		return false, ErrBoxNotFound
	}
	for _, tree := range plan.trees {
		if nil == tree || nil == tree.Root || tree.ID != tree.Root.ID || tree.Box != plan.boxID || box.Exist(tree.Path) {
			return false, errors.New("template document tree plan contains an invalid document snapshot")
		}
	}

	for _, tree := range plan.trees {
		target.DoOperations = append(target.DoOperations, &Operation{
			Action:                "restoreCreatedDoc",
			ID:                    tree.ID,
			Tree:                  tree,
			templateDocTreeRootID: plan.rootID,

View on GitHub (pinned to 8641553a1f)

Solutions

  1. Re-render the template plan against the current state of the document, then apply immediately
  2. Do not rename, move, or edit the root document between plan rendering and transaction submission
  3. Pause or check sync status to avoid remote modifications racing the apply
  4. If the document was deleted, recreate it or render the template from a different root

Example fix

// before
// plan rendered, then user renames the doc, then:
performTransactions([]*Transaction{staleTx}) // fails: root HPath changed
// after
planID, _ := renderTemplateDocTree(boxID, rootID) // re-render right before applying
tx.TemplateDocTreePlanID = planID
performTransactions([]*Transaction{tx})
Defensive patterns

Strategy: retry

Validate before calling

tree, err := loadTreeByBlockID(rootID); if err != nil || tree.HPath != planRootHPath { re-render plan before applying }

Try / catch

if err != nil && strings.Contains(err.Error(), "document used to render the template has changed") { notify user / re-render plan and apply fresh transaction }

Prevention

When it happens

Trigger: The template root document is renamed, moved, or its content changed after the plan was rendered but before the transaction is applied; the document is deleted so LoadTreeByBlockID fails; a concurrent sync/undo/redo rewrote the .sy file.

Common situations: User edits or renames the document while a template preview is open; sync applies remote changes to the same doc between render and apply; an automated script renders plans long before applying them.

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


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