{"record":{"id":"7d07a7351653bc63","repo":"666ghj/MiroFish","slug":"generated-svg-root-is-invalid","errorCode":null,"errorMessage":"generated SVG root is invalid","messagePattern":"generated SVG root is invalid","errorType":"exception","errorClass":"StarHistoryError","httpStatus":null,"severity":"error","filePath":"scripts/star_history.py","lineNumber":1090,"sourceCode":"        decoded_payload = payload.decode(\"utf-8\", errors=\"strict\")\n    except UnicodeDecodeError as exc:\n        raise StarHistoryError(\"generated SVG must be strict UTF-8\") from exc\n    if decoded_payload.startswith(\"\\ufeff\") or \"\\x00\" in decoded_payload:\n        raise StarHistoryError(\"generated SVG must be canonical UTF-8\")\n    upper_payload = decoded_payload.upper()\n    if (\n        \"<!DOCTYPE\" in upper_payload\n        or \"<!ENTITY\" in upper_payload\n        or \"<?\" in decoded_payload\n    ):\n        raise StarHistoryError(\"generated SVG contains forbidden XML directives\")\n    try:\n        root = ET.fromstring(decoded_payload)\n    except ET.ParseError as exc:\n        raise StarHistoryError(\"generated SVG is not valid XML\") from exc\n    svg_namespace = \"{http://www.w3.org/2000/svg}\"\n    if root.tag != f\"{svg_namespace}svg\":\n        raise StarHistoryError(\"generated SVG root is invalid\")\n    allowed_attributes: dict[str, set[str]] = {\n        \"svg\": {\n            \"viewBox\",\n            \"width\",\n            \"height\",\n            \"preserveAspectRatio\",\n            \"role\",\n            \"aria-labelledby\",\n        },\n        \"title\": {\"id\"},\n        \"desc\": {\"id\"},\n        \"rect\": {\n            \"x\",\n            \"y\",\n            \"width\",\n            \"height\",\n            \"rx\",\n            \"fill\",","sourceCodeStart":1072,"sourceCodeEnd":1108,"githubUrl":"https://github.com/666ghj/MiroFish/blob/b5b53acc57189a4a42e44a23e149dc655c98fe82/scripts/star_history.py#L1072-L1108","documentation":"Raised by `_validate_svg` (scripts/star_history.py:1090) when the parsed XML root element is not `{http://www.w3.org/2000/svg}svg` — i.e. the document's outermost element is something else (a wrapper `<div>`, `<g>`, or an `<svg>` missing its namespace declaration). The validator then walks only known-namespaced children, so a wrong root aborts immediately.","triggerScenarios":"Payload parses as XML but the root tag lacks `xmlns=\"http://www.w3.org/2000/svg\"` (then the tag is plain `svg`, not the namespaced one), or the document is wrapped (e.g. someone put the whole chart inside `<html>` or prepended another element before `<svg>`).","commonSituations":"Forks that wrap the SVG in an outer container for embedding; templates that omit the xmlns attribute; tools that 'clean' the SVG and drop the namespace; embedding logic that concatenates a banner element before the svg root.","solutions":["Ensure the document's first and only root element is `<svg xmlns=\"http://www.w3.org/2000/svg\" ...>` with the exact namespace URI.","Remove wrapper elements — if you need surrounding markup, keep it outside the validated artifact and embed the SVG via `<img>`/`<object>` or inline after validation.","If a sanitizer stripped xmlns, re-add it: `root.set(\"xmlns\", \"http://www.w3.org/2000/svg\")` before serialization (or serialize with ET which handles namespaces).","Check for accidental content before the root (comments are fine; elements are not)."],"exampleFix":"# before: wrapper element becomes the root\npayload = b\"<div>\" + svg_body + b\"</div>\"\n\n# after: svg stays the root; wrapper lives outside\nsvg = render_svg(state, theme)          # root is <svg xmlns=...>\nhtml = b\"<div>\" + svg + b\"</div>\"       # embed after validation","handlingStrategy":"try-catch","validationCode":"import xml.etree.ElementTree as ET\nSVG_NS = \"{http://www.w3.org/2000/svg}\"\n\ndef has_svg_root(payload: bytes) -> bool:\n    try:\n        return ET.fromstring(payload).tag == f\"{SVG_NS}svg\"\n    except ET.ParseError:\n        return False","typeGuard":null,"tryCatchPattern":"try:\n    _validate_svg(payload)\nexcept StarHistoryError as exc:\n    if \"root is invalid\" in str(exc):\n        raise ValueError(\"document must be a single root <svg xmlns=...> element\") from exc\n    raise","preventionTips":["Never wrap the SVG in container elements before validation — embed afterwards instead.","Keep xmlns=\"http://www.w3.org/2000/svg\" on the root; sanitizers that strip it will fail here.","Ensure no stray elements precede the <svg> root in concatenated output."],"tags":["svg","xml","namespace","self-check"],"backgroundTag":null,"analyzedSha":"b5b53acc57189a4a42e44a23e149dc655c98fe82","analyzedAt":"2026-08-14T22:29:33.146Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}