{"record":{"id":"63054d3e07233e20","repo":"Textualize/textual","slug":"pop-from-empty-list","errorCode":null,"errorMessage":"pop from empty list","messagePattern":"pop from empty list","errorType":"exception","errorClass":"IndexError","httpStatus":null,"severity":"error","filePath":"src/textual/widgets/_list_view.py","lineNumber":298,"sourceCode":"            An awaitable that yields control to the event loop\n                until the DOM has been updated with the new child item.\n        \"\"\"\n        await_mount = self.mount(*items, before=index)\n        return await_mount\n\n    def pop(self, index: Optional[int] = None) -> AwaitComplete:\n        \"\"\"Remove last ListItem from ListView or\n           Remove ListItem from ListView by index\n\n        Args:\n            index: index of ListItem to remove from ListView\n\n        Returns:\n            An awaitable that yields control to the event loop until\n                the DOM has been updated to reflect item being removed.\n        \"\"\"\n        if len(self) == 0:\n            raise IndexError(\"pop from empty list\")\n\n        index = index if index is not None else -1\n        item_to_remove = self.query(\"ListItem\")[index]\n        normalized_index = index if index >= 0 else index + len(self)\n\n        async def do_pop() -> None:\n            \"\"\"Remove the item and update the highlighted index.\"\"\"\n            await item_to_remove.remove()\n            if self.index is not None:\n                if normalized_index < self.index:\n                    self.index -= 1\n                elif normalized_index == self.index:\n                    old_index = self.index\n                    # Force a re-validation of the index\n                    self.index = self.index\n                    # If the index hasn't changed, the watcher won't be called\n                    # but we need to update the highlighted item\n                    if old_index == self.index:","sourceCodeStart":280,"sourceCodeEnd":316,"githubUrl":"https://github.com/Textualize/textual/blob/06dbeef4bb70fb718236aa418ed658ef4667a126/src/textual/widgets/_list_view.py#L280-L316","documentation":"An IndexError raised by ListView.pop when the list has zero items (len(self) == 0). pop mirrors list semantics: you cannot remove an item from an empty ListView; the check happens before index normalization, so any pop on an empty list fails regardless of the index argument.","triggerScenarios":"Calling list_view.pop() (or pop(i)) after all ListItems were removed or before any were added; a remove-item keybinding handler firing when the list is empty.","commonSituations":"Delete-key handlers bound to ListView that don't check emptiness; popping in a loop driven by external state that empties the list mid-iteration; UI where items are removed asynchronously.","solutions":["Guard the call: if len(list_view): list_view.pop().","Disable or no-op the remove action when list_view.is_empty / len == 0.","Catch IndexError defensively around batch removal loops."],"exampleFix":"# before\nitem = list_view.pop()\n\n# after\nitem = list_view.pop() if len(list_view) else None","handlingStrategy":"validation","validationCode":"item = list_view.pop() if len(list_view) else None","typeGuard":null,"tryCatchPattern":"try:\n    item = list_view.pop()\nexcept IndexError:\n    item = None","preventionTips":["Check len(list_view) before pop in keybinding handlers","Disable remove actions on empty lists","Avoid popping in loops without re-checking emptiness"],"tags":["textual","list-view","index-error","empty-collection"],"backgroundTag":"pop-from-empty-list","analyzedSha":"06dbeef4bb70fb718236aa418ed658ef4667a126","analyzedAt":"2026-08-27T02:36:57.214Z","schemaVersion":2},"datasetVersion":"2026-08-27T03:17:27.898Z"}