{"record":{"id":"b269009793c6020c","repo":"Textualize/textual","slug":"after-argument-must-be-an-index-or-a-treenode-ob","errorCode":null,"errorMessage":"`after` argument must be an index or a TreeNode object to add after","messagePattern":"`after` argument must be an index or a TreeNode object to add after","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"src/textual/widgets/_tree.py","lineNumber":422,"sourceCode":"            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(\n        self,\n        label: TextType,\n        data: TreeDataType | None = None,\n        *,","sourceCodeStart":404,"sourceCodeEnd":440,"githubUrl":"https://github.com/Textualize/textual/blob/06dbeef4bb70fb718236aa418ed658ef4667a126/src/textual/widgets/_tree.py#L404-L440","documentation":"TypeError from TreeNode.add(): the `after` argument is neither an int index nor a TreeNode, so no insertion position can be derived.","triggerScenarios":"`node.add(\"x\", after=3.5)`, `after=\"2\"`, `after=(1,)` or any non-int/non-TreeNode value.","commonSituations":"Index read from user input or JSON as a string; refactor changed the expected type.","solutions":["Convert to int: `after=int(value)`.","Pass the TreeNode instead of an identifier string."],"exampleFix":"# before\nnode.add(\"item\", after=\"1\")\n# after\nnode.add(\"item\", after=int(\"1\"))","handlingStrategy":"type-guard","validationCode":"if not isinstance(after, (int, TreeNode)):\n    after = None\nnode.add(label, after=after)","typeGuard":"from textual.widgets._tree import TreeNode\ndef is_position(n: object) -> bool:\n    return isinstance(n, (int, TreeNode))","tryCatchPattern":"try:\n    node.add(label, after=pos)\nexcept TypeError:\n    node.add(label)","preventionTips":["Coerce string indices with int() at the boundary","Type-annotate insertion helpers"],"tags":["tree","type-error","insert","textual"],"backgroundTag":"wrong-argument-type","analyzedSha":"06dbeef4bb70fb718236aa418ed658ef4667a126","analyzedAt":"2026-08-27T02:36:57.214Z","schemaVersion":2},"datasetVersion":"2026-08-27T03:17:27.898Z"}