3b1b/manim · error · ValueError

SVG has no content to measure

Error message

SVG has no content to measure

What it means

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.

Source

Thrown at manimlib/mobject/svg/svg_mobject.py:49

# STROKE_WIDTH_CONVERSION in shaders/stroke.wgsl
STROKE_WIDTHS_PER_UNIT: float = 100.0

SVG_HASH_TO_MOB_MAP: dict[int, list[VMobject]] = {}
PATH_TO_POINTS: dict[str, Vect3Array] = {}


def get_svg_content_height(svg_string: str) -> float:
    # Strip root attributes to match SVGMobject.modify_xml_tree,
    # which avoids viewBox unit conversions (e.g. pt to px for dvisvgm)
    root = ET.fromstring(svg_string)
    root.attrib.clear()
    data_stream = io.BytesIO()
    ET.ElementTree(root).write(data_stream)
    data_stream.seek(0)
    svg = se.SVG.parse(data_stream)
    bbox = svg.bbox()
    if bbox is None:
        raise ValueError("SVG has no content to measure")
    return bbox[3] - bbox[1]


def _convert_point_to_3d(x: float, y: float) -> np.ndarray:
    return np.array([x, y, 0.0])


class SVGMobject(VMobject):
    file_name: str = ""
    height: float | None = 2.0
    width: float | None = None

    def __init__(
        self,
        file_name: str = "",
        svg_string: str = "",
        should_center: bool = True,
        height: float | None = None,

View on GitHub (pinned to dee01804d4)

Solutions

  1. Open the SVG in an editor/browser and confirm it contains actual renderable elements (path, rect, circle, ...)
  2. If shapes are only in <defs>, reference them with <use> or move them into the main tree
  3. If you control the pipeline, skip/ignore SVGs whose text contains no shape elements instead of passing them to SVGMobject

Example fix

# before
SVGMobject(svg_string='<svg xmlns="http://www.w3.org/2000/svg"></svg>')  # raises

# after
SVGMobject(svg_string='<svg xmlns="http://www.w3.org/2000/svg"><circle r="10"/></svg>')
Defensive patterns

Strategy: validation

Validate before calling

import re
def svg_has_content(svg_string: str) -> bool:
    return bool(re.search(r'<(path|rect|circle|ellipse|line|polyline|polygon|use|image)\b', svg_string))

if svg_has_content(svg_string):
    SVGMobject(svg_string=svg_string)

Try / catch

try:
    mob = SVGMobject(svg_string=svg_string)
except ValueError:
    mob = Square()  # or skip this asset

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of 3b1b/manim@dee01804d4 (2026-08-14). Data as JSON: /api/errors/6fcdcecb92d58da7. Report an issue: GitHub.