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
- Supply the required name: '<!DOCTYPE html>', '<!ENTITY name "value">'.
- Normalize input before parsing: replace curly quotes with ASCII in declaration regions; re-add a name after bare keywords.
- Catch AssertionError and skip the whole malformed declaration (to the next '>') instead of aborting the whole parse.
- 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
- Never emit bare '<!DOCTYPE>' or '<!ENTITY >' — always include the name token.
- Normalize smart quotes/unicode in declaration regions before parsing.
- Test parsers against minified/legacy HTML corpora.
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
- unexpected '[' char in declaration
- unexpected %r char in declaration
- unsupported '[' char in %s declaration
- unknown status keyword %r in marked section
- unexpected char in internal subset (in %r)
AI-assisted analysis of python/cpython@bc6749cc3b (2026-08-14).
Data as JSON: /api/errors/efa4a81251d3978c.
Report an issue: GitHub.