{"record":{"id":"d7052e18d61c92e3","repo":"roboflow/supervision","slug":"failed-to-parse-xml-root-from-annotation-path","errorCode":null,"errorMessage":"Failed to parse XML root from {annotation_path}","messagePattern":"Failed to parse XML root from (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"src/supervision/dataset/formats/pascal_voc.py","lineNumber":240,"sourceCode":"    classes: list[str] = []\n    annotations = {}\n\n    for image_path in tqdm(\n        image_paths,\n        total=len(image_paths),\n        desc=\"Loading Pascal VOC annotations\",\n        disable=not show_progress,\n    ):\n        image_stem = Path(image_path).stem\n        annotation_path = os.path.join(annotations_directory_path, f\"{image_stem}.xml\")\n        if not os.path.exists(annotation_path):\n            annotations[image_path] = Detections.empty()\n            continue\n\n        tree = parse(annotation_path)\n        root = tree.getroot()\n        if root is None:\n            raise ValueError(f\"Failed to parse XML root from {annotation_path}\")\n\n        image = cv2.imread(image_path)\n        if image is None:\n            raise ValueError(f\"Could not read image from path: {image_path}\")\n        resolution_wh = (image.shape[1], image.shape[0])\n        annotation, classes = detections_from_xml_obj(\n            root, classes, resolution_wh, force_masks\n        )\n        annotations[image_path] = annotation\n\n    return classes, image_paths, annotations\n\n\ndef detections_from_xml_obj(\n    root: Element,\n    classes: list[str],\n    resolution_wh: tuple[int, int],\n    force_masks: bool = False,","sourceCodeStart":222,"sourceCodeEnd":258,"githubUrl":"https://github.com/roboflow/supervision/blob/7f254d9784d4c37e0f03cd89ddee164c8db099c0/src/supervision/dataset/formats/pascal_voc.py#L222-L258","documentation":"Raised while loading a Pascal VOC dataset when ElementTree parses the annotation XML file but tree.getroot() returns None. This only happens for a structurally empty or degenerate XML document (e.g. a zero-byte or whitespace-only .xml file), because xml.etree.ElementTree.parse raises ParseError itself for malformed syntax. The file path is included so you can locate the offending annotation.","triggerScenarios":"Calling DetectionDataset.from_pascal_voc(...) (or the internal load loop in pascal_voc.py) where an image stem has a matching .xml file in the annotations directory that is empty, contains only whitespace, or is otherwise a valid-but-rootless document.","commonSituations":"Interrupted dataset downloads or exports that left 0-byte .xml files; annotation writers that flush an empty file before crashing; placeholder files created by tooling; filesystem corruption after a bad copy.","solutions":["Check the file named in the error message with `cat`/`ls -la` — it is almost certainly empty or whitespace-only.","Delete or regenerate the broken .xml file (re-export from the source dataset or re-download).","Sweep the annotations directory for other empty XML files: find annotations_dir -name '*.xml' -size -1c","If empty XML means 'no objects', decide whether to remove the file (the loader then treats the image as empty via the missing-file branch) or write a valid <annotation></annotation> root."],"exampleFix":"# before: empty file annotations/0001.xml (0 bytes)\n# after: minimal valid Pascal VOC file\nwith open('annotations/0001.xml', 'w') as f:\n    f.write('<annotation></annotation>')","handlingStrategy":"validation","validationCode":"from pathlib import Path\nimport xml.etree.ElementTree as ET\n\ndef valid_voc_xml(path: str) -> bool:\n    \"\"\"Check that a Pascal VOC annotation file has a parseable root element.\"\"\"\n    p = Path(path)\n    if not p.exists() or p.stat().st_size == 0:\n        return False\n    try:\n        return ET.parse(p).getroot() is not None\n    except ET.ParseError:\n        return False","typeGuard":null,"tryCatchPattern":"try:\n    dataset = sv.DetectionDataset.from_pascal_voc(images_dir, ann_dir)\nexcept ValueError as e:\n    if 'Failed to parse XML root' in str(e):\n        bad = str(e).split('from ')[-1].strip()\n        Path(bad).unlink(missing_ok=True)  # or quarantine\n        dataset = sv.DetectionDataset.from_pascal_voc(images_dir, ann_dir)\n    else:\n        raise","preventionTips":["Validate dataset archives after download (check for 0-byte XML files).","Keep annotation writers atomic: write to a temp file and rename on success.","Run a one-off sweep: find annotations -name '*.xml' -size -1c before loading."],"tags":["pascal-voc","dataset","xml","parsing"],"backgroundTag":null,"analyzedSha":"7f254d9784d4c37e0f03cd89ddee164c8db099c0","analyzedAt":"2026-08-15T05:13:01.950Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}