rust-lang/rust · error · RuntimeError
Cannot parse an HTML file {!r}: {}
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').
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 NoneView on GitHub (pinned to 7088e4b63a)
Solutions
- Open the referenced file and locate the malformed markup around the parser's reported offset.
- If the HTML is genuinely broken, file a rustdoc bug and xfail/skip the test temporarily.
- Ensure the file is actually HTML (not a 404 page or redirect) and is valid UTF-8.
- 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
- Treat invalid rustdoc HTML as a rustdoc regression, not a test-authoring issue.
- Validate generated HTML parses before committing a directive that queries it.
- Watch for encoding/entity errors when rustdoc emits unusual characters.
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
- line {}: {}
- Non-absolute XPath is not supported due to implementation is
- Tried to use the previous path in the first command
- glob path does not resolve to one file
- File does not exist {!r}
AI-assisted analysis of rust-lang/rust@7088e4b63a (2026-08-10).
Data as JSON: /api/errors/e6c1c23a0843eddc.
Report an issue: GitHub.