rust-lang/rust · error · RuntimeError

Cannot parse an HTML file

Error message

Cannot parse an HTML file {!r}: {}

What it means

Raised as RuntimeError by CachedFiles.get_tree() when ET.fromstringlist() (using the CustomHTMLParser) fails to parse the file as HTML/XML. The custom parser is lenient about void elements and empty attributes but will still throw on malformed markup; the original parse exception is embedded in the message. Note the code suppresses the chain (FIXME: py2, should use 'raise ... from').

Solutions

  1. Open the referenced file and locate the malformed markup around the parser's reported offset.
  2. If the HTML is genuinely broken, file a rustdoc bug and xfail/skip the test temporarily.
  3. Ensure the file is actually HTML (not a 404 page or redirect) and is valid UTF-8.
  4. If an entity is the culprit, confirm it is a named HTML entity the parser knows.

Example fix

// before - rustdoc emitted an unbalanced tag
<div class='item'><span>foo</div>

// after - fix the source HTML so tags are properly closed
<div class='item'><span>foo</span></div>
Defensive patterns

Strategy: try-catch

Validate before calling

from pathlib import Path
from xml.etree import ElementTree as ET

def html_parses_cleanly(abspath) -> bool:
    try:
        with open(abspath, encoding="utf-8") as f:
            ET.fromstringlist(f.readlines(), CustomHTMLParser())
        return True
    except Exception as e:
        return False

if not html_parses_cleanly(os.path.join(doc_root, path)):
    raise SystemExit(f"htmldocck cannot parse {path!r} as HTML; inspect the file")

Type guard

null

Try / catch

try:
    tree = cache.get_tree(path)
except RuntimeError as e:
    if "Cannot parse an HTML file" in str(e):
        logging.error("rustdoc produced unparseable HTML for %s; file a rustdoc bug", path)
    raise

Prevention

When it happens

Trigger: A directive triggers get_tree() on a file that exists but whose content the parser cannot turn into an ElementTree: unclosed tags that aren't void elements, encoding issues, content that is not HTML at all, or an HTMLParser error during entity/charref handling.

Common situations: rustdoc regressed and emitted invalid HTML; the file is actually a redirect/placeholder (not real HTML); an entity reference in the document is not in name2codepoint; encoding mismatch (file declared utf-8 but contains invalid bytes).

Related errors


AI-assisted analysis of rust-lang/rust@7088e4b63a (2026-08-10). Data as JSON: /api/errors/e6c1c23a0843eddc. Report an issue: GitHub.

Appendix: source

Thrown at src/etc/htmldocck.py:280

        with io.open(abspath, encoding="utf-8") as f:
            data = f.read()
            self.files[path] = data
            return data

    def get_tree(self, path):
        path = self.resolve_path(path)
        if path in self.trees:
            return self.trees[path]

        abspath = self.get_absolute_path(path)
        if not (os.path.exists(abspath) and os.path.isfile(abspath)):
            raise FailedCheck("File does not exist {!r}".format(path))

        with io.open(abspath, encoding="utf-8") as f:
            try:
                tree = ET.fromstringlist(f.readlines(), CustomHTMLParser())
            except Exception as e:
                raise RuntimeError(  # noqa: B904 FIXME: py2
                    "Cannot parse an HTML file {!r}: {}".format(path, e)
                )
            self.trees[path] = tree
            return self.trees[path]

    def get_dir(self, path):
        path = self.resolve_path(path)
        abspath = self.get_absolute_path(path)
        if not (os.path.exists(abspath) and os.path.isdir(abspath)):
            raise FailedCheck("Directory does not exist {!r}".format(path))


def check_string(data, pat, regexp):
    pat = pat.replace("{{channel}}", channel)
    if not pat:
        return True  # special case a presence testing
    elif regexp:
        return re.search(pat, data, flags=re.UNICODE) is not None

View on GitHub (pinned to 7088e4b63a)