siyuan-note/siyuan · error

template document tree plan contains an invalid document sna

Error message

template document tree plan contains an invalid document snapshot

What it means

Every child document tree stored in the plan is validated before its restoreCreatedDoc operation is appended: it must be non-nil with a valid root whose ID matches, belong to the plan's notebook, and its on-disk path must NOT already exist (box.Exist). This error means a snapshot in the plan is corrupt or a child document file already exists at the planned path, so restoring would clash with an existing document.

Source

Thrown at kernel/model/template_doc_tree.go:503

	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,
		})
	}
	for index := len(plan.trees) - 1; 0 <= index; index-- {
		tree := plan.trees[index]
		target.UndoOperations = append(target.UndoOperations, &Operation{
			Action:                "removeCreatedDoc",
			ID:                    tree.ID,
			Tree:                  tree,
			templateDocTreeRootID: plan.rootID,

View on GitHub (pinned to 8641553a1f)

Solutions

  1. Re-render the plan so the snapshots reflect current disk state, then apply once
  2. Delete or rename the conflicting existing documents at the planned child paths, or let the plan pick new IDs
  3. Apply each plan exactly once; a partially applied plan leaves files that make re-runs fail
  4. Check sync: ensure no other client created the same documents concurrently
Defensive patterns

Strategy: validation

Validate before calling

for _, t := range planChildPaths { if fileExists(filepath.Join(dataDir, boxID, t)) { resolve conflicts (rename/delete) before attaching the plan } }

Try / catch

if err != nil && strings.Contains(err.Error(), "invalid document snapshot") { re-render the plan; if a child path exists, delete or rename it first, then apply once }

Prevention

When it happens

Trigger: A child document with the same path was created (by sync, another client, or a previous partially-applied plan) after the plan was rendered; the plan's in-memory trees were corrupted; a plan ID is reused against a workspace where the target files exist.

Common situations: Applying the same template twice without re-rendering; sync creating the target documents before the transaction lands; restoring a workspace snapshot while a stale plan is in flight.

Understand the failure class

Background: "already exists" / EEXIST / FileAlreadyExistsException: what the 'file already exists' error means and how to fix it — this error's family across 37 libraries.

Related errors


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