D4Vinci/Scrapling · error · ValueError
`itertag` prefix {prefix!r} is not defined in `namespaces`
Error message
`itertag` prefix {prefix!r} is not defined in `namespaces` What it means
The XML feed template resolves itertag prefixes against the class's namespaces mapping. When itertag is like 'atom:entry' and the prefix ('atom') is not a key in namespaces, _wanted_tag() raises ValueError because the namespace URI needed to match elements is unknown.
Source
Thrown at scrapling/spiders/templates/feed.py:81
for node in self._iter_nodes(root):
async for result in self.parse_node(response, node):
yield result
async def parse_node(
self, response: "Response", node: _Element
) -> AsyncGenerator[Union[Dict[str, Any], Request, None], None]:
"""Override to process one feed node; `node` is a namespace-stripped `lxml` element."""
raise NotImplementedError(f"{self.__class__.__name__} must implement parse_node() method")
yield # Make this a generator for type checkers
def _wanted_tag(self) -> Tuple[Optional[str], str]:
"""Resolve `itertag` into a `(namespace uri or None, localname)` pair."""
prefix, _, name = self.itertag.rpartition(":")
if not prefix:
return None, name
uri = dict(self.namespaces).get(prefix)
if not uri:
raise ValueError(f"`itertag` prefix {prefix!r} is not defined in `namespaces`")
return uri, name
def _iter_nodes(self, root: _Element) -> Iterator[_Element]:
uri, name = self._wanted_tag()
for el in root.iter():
if isinstance(el.tag, str):
qname = etree.QName(el.tag)
if qname.localname == name and (uri is None or qname.namespace == uri):
yield self._strip_namespaces(el)
@staticmethod
def _strip_namespaces(node: _Element) -> _Element:
"""Return a copy of `node` with namespaces removed from every tag and attribute."""
node = deepcopy(node)
for el in node.iter():
if isinstance(el.tag, str):
el.tag = etree.QName(el.tag).localname
for key in list(el.attrib):View on GitHub (pinned to 5d213a2d47)
Solutions
- Add the prefix->URI mapping to the class: namespaces = {"atom": "http://www.w3.org/2005/Atom"} and keep itertag = "atom:entry"
- Or use a localname-only itertag ("entry") if you want to match the tag in any namespace (uri is None matches all namespaces)
Example fix
// before
class Feed(XMLFeedSpider):
itertag = "atom:entry"
// after
class Feed(XMLFeedSpider):
itertag = "atom:entry"
namespaces = {"atom": "http://www.w3.org/2005/Atom"} Defensive patterns
Strategy: validation
Validate before calling
prefix = itertag.rpartition(":")[0]
if prefix and prefix not in dict(namespaces):
raise ValueError(f"{prefix!r} missing from namespaces") Prevention
- Copy itertag and namespaces together from examples
- Use localname itertags (no prefix) to match any namespace
- Add a unit test that calls _wanted_tag() for validation
When it happens
Trigger: Setting itertag = "atom:entry" without a matching namespaces = {"atom": "http://www.w3.org/2005/Atom"} on the class; typos in either the prefix or the namespaces key; overriding namespaces with an empty dict while keeping a prefixed itertag.
Common situations: Copy-pasting an itertag from feed examples without the namespace table that accompanied it; feeds that changed their namespace prefix over time; case mismatches between prefix and namespaces key.
Related errors
- {self.__class__.__name__} must implement parse_node() method
- Cannot use 'proxy_rotator' together with 'proxy' or 'proxies
- Unknown parser argument: "{key}"; maybe you meant {cls.parse
- You must pass a keyword to configure, current keywords: {cls
- Invalid proxy string!
AI-assisted analysis of D4Vinci/Scrapling@5d213a2d47 (2026-08-14).
Data as JSON: /api/errors/689f2ac075472979.
Report an issue: GitHub.