Repository navigation
Description
Bug report
Bug description
Passing an empty path to find(), findall() or findtext() (or to xml.etree.ElementPath directly) raises a confusing TypeError instead of returning a result or a clear error. Whether it happens depends on which implementation runs and on whether namespaces is passed.
With the C accelerator:
import xml.etree.ElementTree as ET
from xml.etree import ElementPath
root = ET.Element("root")
root.findall("") # []
root.findall("", namespaces={}) # TypeError: 'NoneType' object is not iterable
ElementPath.findall(root, "") # TypeError: 'NoneType' object is not iterableWith the pure-Python implementation (the fallback used when _elementtree is unavailable), all of them fail:
import sys
sys.modules["_elementtree"] = None
import xml.etree.ElementTree as ET
root = ET.Element("root")
root.findall("") # TypeError: 'NoneType' object is not iterable
root.find("") # TypeError: 'NoneType' object is not an iterator
root.findtext("", default="D") # TypeError: 'NoneType' object is not an iteratorCause. ElementPath.iterfind() is a plain function, not a generator. For an empty path the tokenizer yields nothing, and the function does a bare return:
try:
token = next()
except StopIteration:
returnSo it returns None instead of an iterator, and findall(), find() and findtext() then call list() or next() on None. The C accelerator only avoids this for a plain path without namespaces: its fast path treats "" as a tag name and returns [], None or the default.
Expected. The same result in both implementations, with or without namespaces. That could be either an empty result ([], None, the default), matching the C fast path, or a clear SyntaxError("invalid path"), which iterfind() already raises a few lines later for other incomplete paths. A minimal fix would be return iter(()) instead of the bare return.
I'm happy to open a PR.
CPython versions tested on:
CPython main branch, 3.14, 3.13, 3.12
Operating systems tested on:
Linux
Activity
picnixz commentedon Nov 11, 2026
I think we should return a list for findall() and the default for findtext(). But I don't want to complicate the code too much. OTOH, we can document that empty path shold not be given and leave that as a doc issue only,.