{"record":{"id":"efa4a81251d3978c","repo":"python/cpython","slug":"expected-name-token-at-r","errorCode":null,"errorMessage":"expected name token at %r","messagePattern":"expected name token at %r","errorType":"exception","errorClass":"AssertionError","httpStatus":null,"severity":"error","filePath":"Lib/_markupbase.py","lineNumber":390,"sourceCode":"                    return j\n\n    # Internal -- scan a name token and the new position and the token, or\n    # return -1 if we've reached the end of the buffer.\n    def _scan_name(self, i, declstartpos):\n        rawdata = self.rawdata\n        n = len(rawdata)\n        if i == n:\n            return None, -1\n        m = _declname_match(rawdata, i)\n        if m:\n            s = m.group()\n            name = s.strip()\n            if (i + len(s)) == n:\n                return None, -1  # end of buffer\n            return name.lower(), m.end()\n        else:\n            self.updatepos(declstartpos, i)\n            raise AssertionError(\n                \"expected name token at %r\" % rawdata[declstartpos:declstartpos+20]\n            )\n\n    # To be overridden -- handlers for unknown objects\n    def unknown_decl(self, data):\n        pass\n","sourceCodeStart":372,"sourceCodeEnd":397,"githubUrl":"https://github.com/python/cpython/blob/bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6/Lib/_markupbase.py#L372-L397","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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()."],"exampleFix":"# before\nHTMLParser().feed('<!DOCTYPE>')  # AssertionError: expected name token\nHTMLParser().feed('<!ENTITY \"e\" \"x\">')\n\n# after\nHTMLParser().feed('<!DOCTYPE html>')\nHTMLParser().feed('<!ENTITY e \"x\">')","handlingStrategy":"validation","validationCode":"import re\n_NAME = re.compile(r'[A-Za-z_:][-A-Za-z0-9._:]*\\s*$')\n\ndef decl_names_ok(raw: str) -> bool:\n    for m in re.finditer(r'<!\\s*(doctype|element|entity|attlist|notation)\\s*([^\\s>]*)', raw, re.I):\n        if not _NAME.match(m.group(2)):\n            return False\n    return True","typeGuard":null,"tryCatchPattern":"try:\n    parser.feed(data)\nexcept AssertionError as e:\n    if 'expected name token' in str(e):\n        data = re.sub(r'<!DOCTYPE\\s*>', '<!DOCTYPE html>', data)\n        parser.reset(); parser.feed(data)\n    else:\n        raise","preventionTips":["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."],"tags":["markup","html-parser","parsing","malformed-html"],"backgroundTag":null,"analyzedSha":"bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6","analyzedAt":"2026-08-14T22:01:13.976Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}