3b1b/manim · error · ValueError
Invalid markup string \"{markup_str}\"\n{validate_error}
Error message
Invalid markup string \"{markup_str}\"\n{validate_error} What it means
Raised by markup_to_svg (text_mobject.py:64) when manimpango's MarkupUtils.validate reports the string is not valid Pango markup. Text() uses Pango markup, so raw '&', '<', '>' and unknown/mismatched tags (<tts>, <b> without </b>) all fail validation before rendering.
Source
Thrown at manimlib/mobject/svg/text_mobject.py:64
"RIGHT": 2
}
def __init__(self, s: str):
self.value = _Alignment.VAL_DICT[s.upper()]
@lru_cache(maxsize=128)
@cache_on_disk
def markup_to_svg(
markup_str: str,
justify: bool = False,
indent: float = 0,
alignment: str = "CENTER",
line_width: float | None = None,
) -> str:
validate_error = manimpango.MarkupUtils.validate(markup_str)
if validate_error:
raise ValueError(
f"Invalid markup string \"{markup_str}\"\n" + \
f"{validate_error}"
)
# `manimpango` is under construction,
# so the following code is intended to suit its interface
alignment = _Alignment(alignment)
if line_width is None:
pango_width = -1
else:
pango_width = line_width / FRAME_WIDTH * DEFAULT_PIXEL_WIDTH
# Write the result to a temporary svg file, and return it's contents.
temp_file = Path(tempfile.gettempdir(), hash_string(markup_str)).with_suffix(".svg")
manimpango.MarkupUtils.text2svg(
text=markup_str,
font="", # Already handled
slant="NORMAL", # Already handledView on GitHub (pinned to dee01804d4)
Solutions
- Escape special characters with html.escape()/xml.sax.saxutils.escape() before passing user data to Text()
- Fix the markup tags: every opened tag must be closed and must be a Pango-supported tag (b, i, u, s, sub, sup, span, ...)
- For literal angle brackets/ampersands use < > & entities
Example fix
# before
Text('Tom & Jerry <3') # invalid markup -> raises
# after
import html
Text(html.escape('Tom & Jerry <3')) Defensive patterns
Strategy: validation
Validate before calling
from xml.sax.saxutils import escape
import re
def safe_markup(s: str) -> str:
# escape bare & < > unless the string already looks like deliberate markup
if re.search(r'<(b|i|u|s|sub|sup|span)\b', s):
return s # author-supplied markup; trust it
return escape(s)
Text(safe_markup(user_string)) Try / catch
import manimpango
try:
Text(markup_str)
except ValueError as e:
if 'Invalid markup string' in str(e):
from xml.sax.saxutils import escape
Text(escape(markup_str)) Prevention
- html.escape() any user- or data-supplied text before Text()
- Close every Pango tag you open; use only supported tags
- Use & < > entities for literal special characters
When it happens
Trigger: Text('A & B'); Text('<b>bold'); Text('<tts>hi</tts>') with an unsupported tag; markup built by string concatenation that leaves a dangling '<'. Markup like '<b>bold</b>' and '<i>i</i>' is valid.
Common situations: Rendering user-supplied or dynamically composed strings containing XML special characters; switching from Tex/PlainText assumptions to Text() which parses markup; version changes in manimpango that alter the accepted tag set.
Related errors
- At least 2 mobjects needed for Union.
- At least 2 mobjects needed for Intersection.
- At least 2 mobjects needed for Exclusion.
- Invalid input sample type
- Mobject cannot contain self
AI-assisted analysis of 3b1b/manim@dee01804d4 (2026-08-14).
Data as JSON: /api/errors/6844c4c80183997f.
Report an issue: GitHub.