python/cpython · error · AssertionError
unexpected '[' char in declaration
Error message
unexpected '[' char in declaration
What it means
AssertionError raised by _markupbase.ParserBase._scan_decl when a '[' appears inside a declaration whose type is not doctype, attlist, linktype, link, or element. It mirrors the sibling 'unsupported' error but fires for unrecognized declaration keywords, e.g. an internal-subset-only construct appearing at top level where the scanner cannot dispatch it.
Source
Thrown at Lib/_markupbase.py:132
if not m:
return -1 # incomplete
j = m.end()
elif c in "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ":
name, j = self._scan_name(j, i)
elif c in self._decl_otherchars:
j = j + 1
elif c == "[":
# this could be handled in a separate doctype parser
if decltype == "doctype":
j = self._parse_doctype_subset(j + 1, i)
elif decltype in {"attlist", "linktype", "link", "element"}:
# must tolerate []'d groups in a content model in an element declaration
# also in data attribute specifications of attlist declaration
# also link type declaration subsets in linktype declarations
# also link attribute specification lists in link declarations
raise AssertionError("unsupported '[' char in %s declaration" % decltype)
else:
raise AssertionError("unexpected '[' char in declaration")
else:
raise AssertionError("unexpected %r char in declaration" % rawdata[j])
if j < 0:
return j
return -1 # incomplete
# Internal -- parse a marked section
# Override this to handle MS-word extension syntax <![if word]>content<![endif]>
def parse_marked_section(self, i, report=1):
rawdata= self.rawdata
assert rawdata[i:i+3] == '<![', "unexpected call to parse_marked_section()"
sectName, j = self._scan_name( i+3, i )
if j < 0:
return j
if sectName in {"temp", "cdata", "ignore", "include", "rcdata"}:
# look for standard ]]> ending
match= _markedsectionclose.search(rawdata, i+3)
elif sectName in {"if", "else", "endif"}:View on GitHub (pinned to bc6749cc3b)
Solutions
- Sanitize input: remove unknown '<!...>' blocks before feeding the parser.
- Wrap feed() in try/except AssertionError and resume after the closing '>' of the bad construct (find it with rawdata.find('>')).
- For conditional comments <![if ...]>, subclass HTMLParser and override parse_marked_section / unknown_decl instead of letting the base scanner see them.
- Validate markup with a tolerant library (bleach, html5lib) if input provenance is untrusted.
Example fix
# before
HTMLParser().feed('<!custom [ data ]>') # AssertionError: unexpected '[' char in declaration
# after
import re
feed = re.sub(r'<![!\w-]*\s*\[.*?\]?>?', '', raw) # strip bracketed decls
HTMLParser().feed(feed) Defensive patterns
Strategy: try-catch
Validate before calling
import re
_DECL_OK = re.compile(r'<!\s*(doctype|element|attlist|entity|notation)\b[^\[]*>', re.I)
def declarations_ok(raw: str) -> bool:
return all(_DECL_OK.match(d) or '[' not in d for d in re.findall(r'<![^>]*>', raw)) Try / catch
try:
parser.feed(data)
except AssertionError as e:
if 'declaration' in str(e):
bad = data.rfind('<!', 0, parser.offset + 1)
data = data[:bad] + data[data.find('>', bad) + 1:]
parser.reset(); parser.feed(data)
else:
raise Prevention
- Sanitize untrusted '<!' constructs before parsing.
- Keep html.parser input to real HTML; route SGML-ish data to SGML tools.
- Wrap feed() centrally so one bad declaration cannot kill the pipeline.
When it happens
Trigger: HTMLParser.feed() on markup like <![ ... ]> handled outside parse_marked_section paths, or <!FOO [ ... ]> where FOO is an unknown declaration keyword containing '['. Any '<!' construct whose scanned name is none of the known types and whose body contains '['.
Common situations: Parsing malformed or machine-generated HTML; conditional-comment-like or MS Office markup fragments reaching the declaration scanner; concatenating fragments so a '<![' begins mid-stream after another declaration's name.
Related errors
- unexpected %r char in declaration
- expected name token at %r
- 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/a8b40a9aab9ad1b3.
Report an issue: GitHub.