{"record":{"id":"e5e86a56de7cdb53","repo":"Textualize/textual","slug":"the-node-specified-for-after-is-not-a-child-of-t","errorCode":null,"errorMessage":"The node specified for `after` is not a child of this node","messagePattern":"The node specified for `after` is not a child of this node","errorType":"exception","errorClass":"AddNodeError","httpStatus":null,"severity":"error","filePath":"src/textual/widgets/_tree.py","lineNumber":418,"sourceCode":"                except ValueError:\n                    raise AddNodeError(\n                        \"The node specified for `before` is not a child of this node\"\n                    )\n            else:\n                raise TypeError(\n                    \"`before` argument must be an index or a TreeNode object to add before\"\n                )\n\n        if after is not None:\n            if isinstance(after, int):\n                insert_index = after + 1\n                if after < 0:\n                    insert_index += len(self.children)\n            elif isinstance(after, TreeNode):\n                try:\n                    insert_index = self.children.index(after) + 1\n                except ValueError:\n                    raise AddNodeError(\n                        \"The node specified for `after` is not a child of this node\"\n                    )\n            else:\n                raise TypeError(\n                    \"`after` argument must be an index or a TreeNode object to add after\"\n                )\n\n        text_label = self._tree.process_label(label)\n        node = self._tree._add_node(self, text_label, data)\n        node._expanded = expand\n        node._allow_expand = allow_expand\n        self._updates += 1\n        self._children.insert(insert_index, node)\n        self._tree._invalidate()\n\n        return node\n\n    def add_leaf(","sourceCodeStart":400,"sourceCodeEnd":436,"githubUrl":"https://github.com/Textualize/textual/blob/06dbeef4bb70fb718236aa418ed658ef4667a126/src/textual/widgets/_tree.py#L400-L436","documentation":"AddNodeError from TreeNode.add(): the `after` argument is a TreeNode that is not a child of this node, so its index (needed to compute insert position index+1) cannot be found.","triggerScenarios":"`node.add(\"x\", after=some_node)` where some_node has a different parent, was removed, or belongs to another subtree.","commonSituations":"Reusing TreeNode references captured before a `clear()`/reload; appending after a node obtained from `tree.get_node_by_id` under a different branch.","solutions":["Check `after_node in node.children` before calling add.","Re-query the node from the tree after any structural mutation.","Insert via the target node's actual parent: `after_node.parent.add(\"x\", after=after_node)`."],"exampleFix":"# before\nnode.add(\"new\", after=stale_node)\n# after\nif target in node.children:\n    node.add(\"new\", after=target)","handlingStrategy":"validation","validationCode":"if after is not None and after not in node.children:\n    after = None\nnode.add(label, after=after)","typeGuard":"from textual.widgets._tree import TreeNode\ndef is_child(parent: TreeNode, n: object) -> bool:\n    return isinstance(n, TreeNode) and n in parent.children","tryCatchPattern":"from textual.widgets._tree import AddNodeError\ntry:\n    node.add(label, after=ref)\nexcept AddNodeError:\n    node.add(label)","preventionTips":["Re-fetch nodes via get_node_by_id after mutations","Store business keys in node.data, not raw TreeNode refs"],"tags":["tree","stale-reference","insert","textual"],"backgroundTag":"stale-node-reference","analyzedSha":"06dbeef4bb70fb718236aa418ed658ef4667a126","analyzedAt":"2026-08-27T02:36:57.214Z","schemaVersion":2},"datasetVersion":"2026-08-27T03:17:27.898Z"}