python/cpython · error · RuntimeError
_markupbase.ParserBase must be subclassed
Error message
_markupbase.ParserBase must be subclassed
What it means
RuntimeError raised by _markupbase.ParserBase.__init__ (Lib/_markupbase.py) when ParserBase itself is instantiated. The class only supplies shared position/declaration-scanning machinery for SGML/HTML/XHTML parsers (html.parser.HTMLParser, html.parser.HTMLParserBase use cases); it has no document handlers, so direct instantiation is blocked.
Source
Thrown at Lib/_markupbase.py:29
_declstringlit_match = re.compile(r'(\'[^\']*\'|"[^"]*")\s*').match
_commentclose = re.compile(r'--\s*>')
_markedsectionclose = re.compile(r']\s*]\s*>')
# An analysis of the MS-Word extensions is available at
# http://web.archive.org/web/20060321153828/http://www.planetpublish.com/xmlarena/xap/Thursday/WordtoXML.pdf
_msmarkedsectionclose = re.compile(r']\s*>')
del re
class ParserBase:
"""Parser base class which provides some common support methods used
by the SGML/HTML and XHTML parsers."""
def __init__(self):
if self.__class__ is ParserBase:
raise RuntimeError(
"_markupbase.ParserBase must be subclassed")
def reset(self):
self.lineno = 1
self.offset = 0
def getpos(self):
"""Return current line number and offset."""
return self.lineno, self.offset
# Internal -- update line number and offset. This should be
# called for each piece of data exactly once, in order -- in other
# words the concatenation of all the input strings to this
# function should be exactly the entire input.
def updatepos(self, i, j):
if i >= j:
return j
rawdata = self.rawdataView on GitHub (pinned to bc6749cc3b)
Solutions
- Subclass ParserBase (adding at least goahead/handlers, or better: subclass html.parser.HTMLParser which composes it) — instantiation of the subclass is allowed.
- Use html.parser.HTMLParser for real HTML parsing needs; _markupbase is an implementation detail.
- If you only need position tracking (lineno/offset), copy the small getpos/updatepos pattern instead of instantiating the base.
- For copy/pickle paths, ensure reconstruction targets the concrete subclass, not ParserBase.
Example fix
# before
import _markupbase
p = _markupbase.ParserBase() # RuntimeError: must be subclassed
# after
from html.parser import HTMLParser
class MyParser(HTMLParser):
pass
p = MyParser() # fine Defensive patterns
Strategy: type-guard
Validate before calling
import _markupbase
def instantiable(cls) -> bool:
return cls is not _markupbase.ParserBase Type guard
import _markupbase
def is_concrete_parser_class(cls) -> bool:
"""True when cls can be instantiated (not the abstract ParserBase itself)."""
return isinstance(cls, type) and issubclass(cls, _markupbase.ParserBase) and cls is not _markupbase.ParserBase Try / catch
try:
p = _markupbase.ParserBase()
except RuntimeError as e:
if 'must be subclassed' in str(e):
class MiniParser(_markupbase.ParserBase):
pass
p = MiniParser()
else:
raise Prevention
- Subclass html.parser.HTMLParser for real work; never instantiate ParserBase.
- Avoid importing private stdlib modules (_markupbase) — they are not a stable API.
- When copy/pickling parser objects, rebuild via the concrete subclass.
When it happens
Trigger: Calling _markupbase.ParserBase() directly. Reached when someone imports the private module to reuse its regex scanning helpers, or a metaclass/copy path (e.g. copy.copy then __init__ re-run on the base) instantiates the base class.
Common situations: Developers reaching for _markupbase to parse fragments; inheriting from the wrong class in a custom parser; copy/deepcopy or pickle round-trips that reconstruct objects through the base __init__.
Related errors
- Expected Theme object, found {t}
- unsupported '[' char in %s declaration
- unexpected '[' char in declaration
- unexpected %r char in declaration
- unknown status keyword %r in marked section
AI-assisted analysis of python/cpython@bc6749cc3b (2026-08-14).
Data as JSON: /api/errors/f2d4f0a91f42450e.
Report an issue: GitHub.