python/cpython · error · AssertionError

expected name token at %r

Error message

expected name token at %r

What it means

AssertionError raised by _markupbase.ParserBase._scan_name when a declaration expects a name token (element/entity name, keyword) at a position where the data does not match the name pattern. The message includes up to 20 characters of the surrounding declaration for context. It signals fundamentally malformed declaration syntax rather than merely unusual content.

Source

Thrown at Lib/_markupbase.py:390

                    return j

    # Internal -- scan a name token and the new position and the token, or
    # return -1 if we've reached the end of the buffer.
    def _scan_name(self, i, declstartpos):
        rawdata = self.rawdata
        n = len(rawdata)
        if i == n:
            return None, -1
        m = _declname_match(rawdata, i)
        if m:
            s = m.group()
            name = s.strip()
            if (i + len(s)) == n:
                return None, -1  # end of buffer
            return name.lower(), m.end()
        else:
            self.updatepos(declstartpos, i)
            raise AssertionError(
                "expected name token at %r" % rawdata[declstartpos:declstartpos+20]
            )

    # To be overridden -- handlers for unknown objects
    def unknown_decl(self, data):
        pass

View on GitHub (pinned to bc6749cc3b)

Solutions

  1. Supply the required name: '<!DOCTYPE html>', '<!ENTITY name "value">'.
  2. Normalize input before parsing: replace curly quotes with ASCII in declaration regions; re-add a name after bare keywords.
  3. Catch AssertionError and skip the whole malformed declaration (to the next '>') instead of aborting the whole parse.
  4. Pre-validate markup cheaply (e.g. require '<!DOCTYPE' be followed by a name char) and repair before feed().

Example fix

# before
HTMLParser().feed('<!DOCTYPE>')  # AssertionError: expected name token
HTMLParser().feed('<!ENTITY "e" "x">')

# after
HTMLParser().feed('<!DOCTYPE html>')
HTMLParser().feed('<!ENTITY e "x">')
Defensive patterns

Strategy: validation

Validate before calling

import re
_NAME = re.compile(r'[A-Za-z_:][-A-Za-z0-9._:]*\s*$')

def decl_names_ok(raw: str) -> bool:
    for m in re.finditer(r'<!\s*(doctype|element|entity|attlist|notation)\s*([^\s>]*)', raw, re.I):
        if not _NAME.match(m.group(2)):
            return False
    return True

Try / catch

try:
    parser.feed(data)
except AssertionError as e:
    if 'expected name token' in str(e):
        data = re.sub(r'<!DOCTYPE\s*>', '<!DOCTYPE html>', data)
        parser.reset(); parser.feed(data)
    else:
        raise

Prevention

When it happens

Trigger: HTMLParser.feed() on <!DOCTYPE> (no name), <!ENTITY > with the name missing, <!ATTLIST 'x' ...> starting with an illegal character, or a truncated declaration where the buffer ends exactly after the keyword so no name follows.

Common situations: Minifiers that strip 'redundant' doctype names; templates emitting '<!DOCTYPE >'; chunked feeds cutting between keyword and name; scraped HTML with typographic quotes/unicode in declaration positions.

Related errors


AI-assisted analysis of python/cpython@bc6749cc3b (2026-08-14). Data as JSON: /api/errors/efa4a81251d3978c. Report an issue: GitHub.