{"record":{"id":"61ad769ed7af6150","repo":"3b1b/manim","slug":"invalid-scene-name","errorCode":null,"errorMessage":"Invalid scene name","messagePattern":"Invalid scene name","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"manimlib/extract_scene.py","lineNumber":57,"sourceCode":"\ndef prompt_user_for_choice(scene_classes):\n    name_to_class = {}\n    max_digits = len(str(len(scene_classes)))\n    for idx, scene_class in enumerate(scene_classes, start=1):\n        name = scene_class.__name__\n        print(f\"{str(idx).zfill(max_digits)}: {name}\")\n        name_to_class[name] = scene_class\n    try:\n        user_input = input(\"\\nSelect which scene to render (by name or number): \")\n        return [\n            name_to_class[split_str] if not split_str.isnumeric() else scene_classes[int(split_str) - 1]\n            for split_str in user_input.replace(\" \", \"\").split(\",\")\n        ]\n    except IndexError:\n        log.error(\"Invalid scene number\")\n        sys.exit(2)\n    except KeyError:\n        log.error(\"Invalid scene name\")\n        sys.exit(2)\n    except EOFError:\n        sys.exit(1)\n\n\ndef compute_total_frames(scene_class, scene_config):\n    \"\"\"\n    When a scene is being written to file, a copy of the scene is run with\n    skip_animations set to true so as to count how many frames it will require.\n    This allows for a total progress bar on rendering, and also allows runtime\n    errors to be exposed preemptively for long running scenes.\n    \"\"\"\n    pre_config = copy.deepcopy(scene_config)\n    pre_config[\"file_writer_config\"][\"write_to_movie\"] = False\n    pre_config[\"file_writer_config\"][\"save_last_frame\"] = False\n    pre_config[\"file_writer_config\"][\"quiet\"] = True\n    pre_config[\"skip_animations\"] = True\n    pre_scene = scene_class(**pre_config)","sourceCodeStart":39,"sourceCodeEnd":75,"githubUrl":"https://github.com/3b1b/manim/blob/dee01804d47b9f94402d71472674710dcac125b8/manimlib/extract_scene.py#L39-L75","documentation":"Same interactive scene-selection path as error 55, but for the name branch: a non-numeric token is looked up in name_to_class (built from each scene class's __name__). An unknown name raises KeyError, caught and logged as 'Invalid scene name', then exit status 2.","triggerScenarios":"Typing a class name with a typo ('MyScnee'), using the file name instead of the class name, wrong casing ('myscene' vs 'MyScene'), or pasting a name of a class that exists in a different file.","commonSituations":"Forgetting the scene class is named Construct not the file name; renaming a class but reusing an old shell command; case-sensitivity surprises.","solutions":["Type the exact scene class name as printed in the menu (case-sensitive)","Copy-paste the name from the numbered list shown above the prompt","Run with -a/--write_all or name the scene on the CLI to avoid interactive selection"],"exampleFix":"# before\n> construct   # class is actually named Construct\n# after\n> Construct","handlingStrategy":"validation","validationCode":"name = input(\"Scene name: \")\nassert name in {c.__name__ for c in scene_classes}, f\"{name!r} is not a scene class name\"","typeGuard":"def is_known_scene_name(name: str, classes: list) -> bool:\n    return name in {c.__name__ for c in classes}","tryCatchPattern":null,"preventionTips":["Scene names are class names — exact, case-sensitive","Copy-paste from the numbered menu manim prints above the prompt"],"tags":["cli","scene-selection","interactive","startup"],"backgroundTag":null,"analyzedSha":"dee01804d47b9f94402d71472674710dcac125b8","analyzedAt":"2026-08-14T19:53:44.241Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}