{"record":{"id":"6fcdcecb92d58da7","repo":"3b1b/manim","slug":"svg-has-no-content-to-measure","errorCode":null,"errorMessage":"SVG has no content to measure","messagePattern":"SVG has no content to measure","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"manimlib/mobject/svg/svg_mobject.py","lineNumber":49,"sourceCode":"# STROKE_WIDTH_CONVERSION in shaders/stroke.wgsl\nSTROKE_WIDTHS_PER_UNIT: float = 100.0\n\nSVG_HASH_TO_MOB_MAP: dict[int, list[VMobject]] = {}\nPATH_TO_POINTS: dict[str, Vect3Array] = {}\n\n\ndef get_svg_content_height(svg_string: str) -> float:\n    # Strip root attributes to match SVGMobject.modify_xml_tree,\n    # which avoids viewBox unit conversions (e.g. pt to px for dvisvgm)\n    root = ET.fromstring(svg_string)\n    root.attrib.clear()\n    data_stream = io.BytesIO()\n    ET.ElementTree(root).write(data_stream)\n    data_stream.seek(0)\n    svg = se.SVG.parse(data_stream)\n    bbox = svg.bbox()\n    if bbox is None:\n        raise ValueError(\"SVG has no content to measure\")\n    return bbox[3] - bbox[1]\n\n\ndef _convert_point_to_3d(x: float, y: float) -> np.ndarray:\n    return np.array([x, y, 0.0])\n\n\nclass SVGMobject(VMobject):\n    file_name: str = \"\"\n    height: float | None = 2.0\n    width: float | None = None\n\n    def __init__(\n        self,\n        file_name: str = \"\",\n        svg_string: str = \"\",\n        should_center: bool = True,\n        height: float | None = None,","sourceCodeStart":31,"sourceCodeEnd":67,"githubUrl":"https://github.com/3b1b/manim/blob/dee01804d47b9f94402d71472674710dcac125b8/manimlib/mobject/svg/svg_mobject.py#L31-L67","documentation":"Raised by get_svg_content_height (svg_mobject.py:49) when the parsed SVG's bounding box is None — svgelements cannot find any drawable content to measure. The function strips root attributes (to skip viewBox unit conversions) and then asks for a bbox; an SVG with only defs/metadata or truly empty content yields None.","triggerScenarios":"Passing an svg_string whose body has no renderable elements, e.g. '<svg xmlns=\"...\"></svg>' or one containing only <defs>, <metadata>, or comments; also a file whose root tag isn't really <svg> so parsing produces nothing measurable.","commonSituations":"Loading placeholder/empty SVG exports from design tools; SVGs whose visible shapes live in <defs> without <use>; corrupted or truncated downloads that parse but contain no shapes.","solutions":["Open the SVG in an editor/browser and confirm it contains actual renderable elements (path, rect, circle, ...)","If shapes are only in <defs>, reference them with <use> or move them into the main tree","If you control the pipeline, skip/ignore SVGs whose text contains no shape elements instead of passing them to SVGMobject"],"exampleFix":"# before\nSVGMobject(svg_string='<svg xmlns=\"http://www.w3.org/2000/svg\"></svg>')  # raises\n\n# after\nSVGMobject(svg_string='<svg xmlns=\"http://www.w3.org/2000/svg\"><circle r=\"10\"/></svg>')","handlingStrategy":"validation","validationCode":"import re\ndef svg_has_content(svg_string: str) -> bool:\n    return bool(re.search(r'<(path|rect|circle|ellipse|line|polyline|polygon|use|image)\\b', svg_string))\n\nif svg_has_content(svg_string):\n    SVGMobject(svg_string=svg_string)","typeGuard":null,"tryCatchPattern":"try:\n    mob = SVGMobject(svg_string=svg_string)\nexcept ValueError:\n    mob = Square()  # or skip this asset","preventionTips":["Pre-validate SVG files contain drawable shape elements before loading","Move shapes out of <defs> or reference them with <use>","Reject empty exports at the asset-intake step of your pipeline"],"tags":["manim","svg","parsing","empty-content"],"backgroundTag":null,"analyzedSha":"dee01804d47b9f94402d71472674710dcac125b8","analyzedAt":"2026-08-14T19:53:44.241Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}