{"record":{"id":"3d1a460d4d7caa8c","repo":"siyuan-note/siyuan","slug":"the-document-used-to-render-the-template-has-chang","errorCode":null,"errorMessage":"the document used to render the template has changed","messagePattern":"the document used to render the template has changed","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/template_doc_tree.go","lineNumber":494,"sourceCode":"\t}\n\n\tplanID := target.TemplateDocTreePlanID\n\ttarget.TemplateDocTreePlanID = \"\"\n\tvalue, loaded := templateDocTreePlans.LoadAndDelete(planID)\n\tif !loaded {\n\t\treturn false, errors.New(\"template document tree plan is missing or has expired\")\n\t}\n\tplan, ok := value.(*templateDocTreePlan)\n\tif !ok || plan.id != planID || time.Now().After(plan.expiresAt) {\n\t\treturn false, errors.New(\"template document tree plan is invalid or has expired\")\n\t}\n\tif !transactionTargetsTemplateRoot(target, plan.rootID, plan.boxID) {\n\t\treturn false, errors.New(\"template document tree plan does not match the edited document\")\n\t}\n\trootTree, loadErr := LoadTreeByBlockID(plan.rootID)\n\tif nil != loadErr || nil == rootTree || rootTree.Box != plan.boxID || rootTree.Path != plan.rootPath ||\n\t\trootTree.HPath != plan.rootHPath {\n\t\treturn false, errors.New(\"the document used to render the template has changed\")\n\t}\n\ttarget.templateDocTreeRootSnapshot = rootTree\n\tbox := Conf.Box(plan.boxID)\n\tif nil == box {\n\t\treturn false, ErrBoxNotFound\n\t}\n\tfor _, tree := range plan.trees {\n\t\tif nil == tree || nil == tree.Root || tree.ID != tree.Root.ID || tree.Box != plan.boxID || box.Exist(tree.Path) {\n\t\t\treturn false, errors.New(\"template document tree plan contains an invalid document snapshot\")\n\t\t}\n\t}\n\n\tfor _, tree := range plan.trees {\n\t\ttarget.DoOperations = append(target.DoOperations, &Operation{\n\t\t\tAction:                \"restoreCreatedDoc\",\n\t\t\tID:                    tree.ID,\n\t\t\tTree:                  tree,\n\t\t\ttemplateDocTreeRootID: plan.rootID,","sourceCodeStart":476,"sourceCodeEnd":512,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/8641553a1f07374001902d3ce773285db1292b2d/kernel/model/template_doc_tree.go#L476-L512","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Re-render the template plan against the current state of the document, then apply immediately","Do not rename, move, or edit the root document between plan rendering and transaction submission","Pause or check sync status to avoid remote modifications racing the apply","If the document was deleted, recreate it or render the template from a different root"],"exampleFix":"// before\n// plan rendered, then user renames the doc, then:\nperformTransactions([]*Transaction{staleTx}) // fails: root HPath changed\n// after\nplanID, _ := renderTemplateDocTree(boxID, rootID) // re-render right before applying\ntx.TemplateDocTreePlanID = planID\nperformTransactions([]*Transaction{tx})","handlingStrategy":"retry","validationCode":"tree, err := loadTreeByBlockID(rootID); if err != nil || tree.HPath != planRootHPath { re-render plan before applying }","typeGuard":null,"tryCatchPattern":"if err != nil && strings.Contains(err.Error(), \"document used to render the template has changed\") { notify user / re-render plan and apply fresh transaction }","preventionTips":["Minimize the window between rendering and applying","Avoid renaming/moving/editing the root document while a plan is pending","Check sync status before applying; apply after sync settles","Detect document-change events and invalidate pending plans"],"tags":["go","transaction","template","stale-state","concurrency"],"backgroundTag":"invalid-state-transition","analyzedSha":"8641553a1f07374001902d3ce773285db1292b2d","analyzedAt":"2026-09-11T16:08:28.414Z","contentChangedAt":"2026-09-11T16:08:28.414Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}