3b1b/manim · error · TypeError

Invalid selector: '{sel}'

Error message

Invalid selector: '{sel}'

What it means

Raised by StringMobject.get_span_indication_parts path (string_mobject.py:204) when a selector in a selector list is of a type the single-selector resolver does not recognize. find_spans_by_single_selector returns None for unsupported types; inside a composite selector list that None triggers this TypeError. Valid single selectors are strings (matched against the string) and (start, end) Span tuples of ints/strings.

Source

Thrown at manimlib/mobject/svg/string_mobject.py:204

                isinstance(index, int) or index is None
                for index in sel
            ):
                l = len(self.string)
                span = tuple(
                    default_index if index is None else
                    min(index, l) if index >= 0 else max(index + l, 0)
                    for index, default_index in zip(sel, (0, l))
                )
                return [span]
            return None

        result = find_spans_by_single_selector(selector)
        if result is None:
            result = []
            for sel in selector:
                spans = find_spans_by_single_selector(sel)
                if spans is None:
                    raise TypeError(f"Invalid selector: '{sel}'")
                result.extend(spans)
        return list(filter(lambda span: span[0] <= span[1], result))

    @staticmethod
    def span_contains(span_0: Span, span_1: Span) -> bool:
        return span_0[0] <= span_1[0] and span_0[1] >= span_1[1]

    # Parsing

    def parse(self) -> None:
        def get_substr(span: Span) -> str:
            return self.string[slice(*span)]

        configured_items = self.get_configured_items()
        isolated_spans = self.find_spans_by_selector(self.isolate)
        protected_spans = self.find_spans_by_selector(self.protect)
        command_matches = self.get_command_matches(self.string)

View on GitHub (pinned to dee01804d4)

Solutions

  1. Use only str selectors or (start, end) tuples of int/string endpoints in selector lists
  2. Convert numeric indices with int() before packing them into a span tuple
  3. Validate each selector: isinstance(sel, str) or (isinstance(sel, tuple) and len(sel) == 2 and all(isinstance(i, (int, str)) for i in sel))

Example fix

# before
mob.get_submobject_from_selector(["abc", (0.5, 1)])  # float span -> raises

# after
mob.get_submobject_from_selector(["abc", (0, 1)])
Defensive patterns

Strategy: type-guard

Validate before calling

def valid_selector(sel) -> bool:
    if isinstance(sel, str):
        return True
    return (isinstance(sel, tuple) and len(sel) == 2
            and all(isinstance(i, (int, str)) for i in sel))

selectors = [s for s in selectors if valid_selector(s)]

Type guard

def is_valid_selector(sel) -> bool:
    if isinstance(sel, str):
        return True
    return (isinstance(sel, tuple) and len(sel) == 2
            and all(isinstance(i, (int, str)) for i in sel))

Prevention

When it happens

Trigger: Calling mob.get_submobject_from_selector or passing sub_str_to_isolate/substrings_to_isolate with a non-str/non-tuple entry, e.g. ['abc', 3] or [(0.5, 1)] (floats, not ints) inside a composite selector list. A plain string alone does not raise (it may match nothing); the mixed list with an invalid element does.

Common situations: Programmatically building selector lists where one element is a number, a regex object, or a span with float indices; assuming regex or index floats are supported like in other APIs.

Related errors


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