{"record":{"id":"891cd89ed830f41a","repo":"siyuan-note/siyuan","slug":"invalid-created-doc-compensation-snapshot","errorCode":null,"errorMessage":"invalid created doc compensation snapshot","messagePattern":"invalid created doc compensation snapshot","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/transaction.go","lineNumber":2871,"sourceCode":"\t\t}\n\t\tif restoreErr := restoreCreatedDocTreeSnapshot(tree); nil != restoreErr {\n\t\t\terr = errors.Join(err, restoreErr)\n\t\t\tcontinue\n\t\t}\n\t\tif box := Conf.Box(tree.Box); nil != box {\n\t\t\tbox.setSortByConf(path.Dir(tree.Path), tree.ID)\n\t\t\tPushCreate(box, tree.Path, nil)\n\t\t}\n\t}\n\tif nil != tx.templateDocTreeRootSnapshot {\n\t\terr = errors.Join(err, restoreCreatedDocTreeSnapshot(tx.templateDocTreeRootSnapshot))\n\t}\n\treturn\n}\n\nfunc restoreCreatedDocTreeSnapshot(tree *parse.Tree) error {\n\tif nil == tree || nil == tree.Root {\n\t\treturn errors.New(\"invalid created doc compensation snapshot\")\n\t}\n\tif err := writeTreeUpsertQueue(tree); nil != err {\n\t\treturn err\n\t}\n\ttreenode.UpsertBlockTree(tree)\n\treturn nil\n}\n\nfunc (tx *Transaction) loadTreeByBlockTree(bt *treenode.BlockTree) (ret *parse.Tree, err error) {\n\tif nil == bt {\n\t\treturn nil, ErrBlockNotFound\n\t}\n\n\tret = tx.trees[bt.RootID]\n\tif nil != ret {\n\t\treturn\n\t}\n","sourceCodeStart":2853,"sourceCodeEnd":2889,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/8641553a1f07374001902d3ce773285db1292b2d/kernel/model/transaction.go#L2853-L2889","documentation":"restoreCreatedDocTreeSnapshot compensates a failed transaction by restoring the tree of a document that was created within it. It throws this error when it is handed a nil tree or a tree with a nil Root, which means the compensation snapshot passed to the transaction rollback path is unusable and the created document's tree cannot be re-persisted.","triggerScenarios":"A transaction includes a document creation, later fails, and the compensation path calls restoreCreatedDocTreeSnapshot with a nil tree or a parse.Tree whose Root is nil (e.g. the tree failed to load/parse before the compensation ran).","commonSituations":"Rollback after a partial multi-doc transaction where the created doc's tree was never indexed; corrupted or not-yet-written .sy file loaded into a tree with no root; a nil result from a tree loader passed straight into the compensation function.","solutions":["Ensure the created document's tree is loaded/parsed successfully before initiating the transaction compensation, and skip or log when no tree exists","Check that the .sy file for the created doc exists and is valid JSON Kramdown in the notebook's data directory","Re-open the notebook / rebuild the index so the tree can be re-fetched, then retry the transaction","Inspect the caller of restoreCreatedDocTreeSnapshot to make sure it does not forward a nil tree from a failed load without handling it"],"exampleFix":"// before\nrestoreCreatedDocTreeSnapshot(tree)\n// after\nif tree != nil && tree.Root != nil {\n    if err := restoreCreatedDocTreeSnapshot(tree); err != nil {\n        logging.LogErrorf(\"restore created doc snapshot failed: %v\", err)\n    }\n}","handlingStrategy":"type-guard","validationCode":"if tree == nil || tree.Root == nil {\n    return errors.New(\"cannot compensate: snapshot tree is empty\")\n}\nrestoreCreatedDocTreeSnapshot(tree)","typeGuard":"func hasRoot(tree *parse.Tree) bool { return tree != nil && tree.Root != nil }","tryCatchPattern":null,"preventionTips":["Never pass a tree obtained from a loader that may return nil into compensation paths without checking","Log and handle tree load failures before entering the transaction rollback","Validate .sy files after restore/import before running transactions"],"tags":["go","transaction","rollback","internal"],"backgroundTag":"internal-invariant-violation","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"}