siyuan-note/siyuan · error
template document tree plan does not match the edited docume
Error message
template document tree plan does not match the edited document
What it means
transactionTargetsTemplateRoot verifies that the transaction's Do/Undo operations actually target the template root document recorded in the plan (plan.rootID/plan.boxID). This error means the plan was rendered from a different document than the one the transaction edits — the plan and transaction are mismatched.
Source
Thrown at kernel/model/template_doc_tree.go:489
}
for _, operation := range append(append([]*Operation{}, target.DoOperations...), target.UndoOperations...) {
if nil != operation && ("restoreCreatedDoc" == operation.Action || "removeCreatedDoc" == operation.Action) {
return false, errors.New("template document tree transaction contains a reserved operation")
}
}
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 {View on GitHub (pinned to 8641553a1f)
Solutions
- Render the plan from the same document (rootID and notebook) that the transaction's parent operations modify
- Ensure the transaction contains at least one operation whose ID (or insert ParentID/PreviousID/NextID) equals plan.rootID in the matching box
- Send one plan per transaction and never share plan IDs across documents
- Re-render the plan if the user switched documents between rendering and applying
Example fix
// before tx.DoOperations = operationsFor(docB) // docB != plan.rootID tx.TemplateDocTreePlanID = planIDFrom(docA) // after tx.DoOperations = operationsFor(planRootDoc) // parent ops must target the plan's root document tx.TemplateDocTreePlanID = planIDFrom(planRootDoc)
Defensive patterns
Strategy: validation
Validate before calling
for _, op := range append(tx.DoOperations, tx.UndoOperations...) { if op.ID != planRootID && op.ParentID != planRootID { abort: plan/transaction document mismatch } } Try / catch
if err != nil && strings.Contains(err.Error(), "does not match the edited document") { re-render the plan for the current document and rebuild the transaction } Prevention
- Always render the plan from the same document the transaction edits
- Bind plan ID to the editor tab/document and discard it on document switch
- Never share plan IDs across notebooks or documents
- Keep one plan per transaction
When it happens
Trigger: Client renders a plan against document A but submits the transaction whose parent operations edit document B; a transaction batch that mixes documents; using a plan ID captured from another editor tab open on a different document.
Common situations: Two editor tabs open, template rendered in tab 1 but transaction sent from tab 2; a script that renders once and applies to several documents; copy-pasted integration code reusing a plan across boxes/notebooks.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- template document tree plan is missing or has expired
- template document tree plan is invalid or has expired
- the document used to render the template has changed
- attribute view [%s] view [%s] not found
- attribute view [%s] has no available view: %w
AI-assisted analysis of siyuan-note/siyuan@8641553a1f (2026-09-11).
Data as JSON: /api/errors/2950596a0d500c38.
Report an issue: GitHub.