Stirling-Tools/Stirling-PDF · error · RuntimeError

Failed to parse {path}: {exc}

Error message

Failed to parse {path}: {exc}

What it means

RuntimeError raised when ElementTree fails to parse a JaCoCo XML coverage report file. The XML is malformed, truncated, or not valid XML, so _xml_parse raises a ParseError which is wrapped into this RuntimeError with the path and underlying exception.

Source

Thrown at scripts/coverage-summary.py:67

    def pct(self) -> float:
        return 100.0 * self.covered / self.total if self.total else 0.0

    def add(self, other: CounterTotals) -> None:
        self.covered += other.covered
        self.missed += other.missed


def _parse_jacoco_xml(path: Path) -> dict[str, CounterTotals]:
    """Read top-level <counter> elements from a JaCoCo report XML.

    ElementTree's default parser doesn't validate the DTD, so JaCoCo's
    `report.dtd` reference is harmless even on offline CI runners.
    Counters are direct children of the <report> root.
    """
    try:
        root = _xml_parse(path).getroot()
    except _XMLParseError as exc:
        raise RuntimeError(f"Failed to parse {path}: {exc}") from exc

    out: dict[str, CounterTotals] = {}
    for counter in root.findall("counter"):
        t = counter.get("type") or ""
        if t not in JACOCO_COUNTERS:
            continue
        out[t] = CounterTotals(
            covered=int(counter.get("covered") or 0),
            missed=int(counter.get("missed") or 0),
        )
    return out


def _bar(pct: float, width: int = 20) -> str:
    """Render a fixed-width ASCII progress bar. Markdown-safe on all consoles."""
    filled = int(round(pct / 100.0 * width))
    return "[" + "#" * filled + "-" * (width - filled) + "]"

View on GitHub (pinned to 9ef20dcab8)

Solutions

  1. Validate the XML: xmllint <path> to see the parse error location.
  2. Re-run the JaCoCo test/coverage generation to produce a complete report.
  3. Ensure the path glob only matches fully-written JaCoCo report XML files.
Defensive patterns

Strategy: try-catch

Validate before calling

# Validate XML before parsing the report
import xml.dom.minidom as M
try:
    M.parse(str(path))
except Exception as e:
    print(f"Invalid XML {path}: {e}", file=sys.stderr)

Try / catch

try:
    root = _xml_parse(path).getroot()
except _XMLParseError as exc:
    raise RuntimeError(f"Failed to parse {path}: {exc}") from exc

Prevention

When it happens

Trigger: Running scripts/coverage-summary.py against a JaCoCo report XML that is empty, truncated, contains invalid characters, or is not well-formed XML.

Common situations: JaCoCo was killed mid-write, leaving a truncated report. A glob pattern matched a non-XML file or an empty placeholder. Encoding issues in the report.

Understand the failure class

Related errors


AI-assisted analysis of Stirling-Tools/Stirling-PDF@9ef20dcab8 (2026-08-13). Data as JSON: /api/errors/5f704c48594ff7b3. Report an issue: GitHub.