{"record":{"id":"8f32d80a9d57fa3d","repo":"HKUDS/DeepTutor","slug":"image-mode-code-must-only-contain-yon-image-anchor","errorCode":null,"errorMessage":"Image mode code must only contain YON_IMAGE anchor blocks.","messagePattern":"Image mode code must only contain YON_IMAGE anchor blocks\\.","errorType":"exception","errorClass":"ManimRenderError","httpStatus":null,"severity":"warning","filePath":"deeptutor/agents/math_animator/renderer.py","lineNumber":93,"sourceCode":"            code_path=code_path, scene_name=scene_name, quality=quality, save_last_frame=False\n        )\n        video_file = self._find_rendered_file(\".mp4\")\n        target_name = slugify_filename(f\"{self.turn_id}-{scene_name}.mp4\", f\"{self.turn_id}.mp4\")\n        artifact_path = self.artifacts_dir / target_name\n        artifact_path.write_bytes(video_file.read_bytes())\n        await self._emit_progress(f\"Saved rendered video as {artifact_path.name}.\")\n        return self._build_artifact(artifact_path, \"video\", \"video/mp4\", \"Animation video\")\n\n    async def _render_image_blocks(self, *, code: str, quality: str) -> list[RenderedArtifact]:\n        matches = list(YON_IMAGE_PATTERN.finditer(code))\n        if not matches:\n            raise ManimRenderError(\n                \"Image mode requires code blocks wrapped in ### YON_IMAGE_n_START ### / END ###.\"\n            )\n\n        residual = YON_IMAGE_PATTERN.sub(\"\", code).strip()\n        if residual:\n            raise ManimRenderError(\"Image mode code must only contain YON_IMAGE anchor blocks.\")\n\n        artifacts: list[RenderedArtifact] = []\n        for idx, match in enumerate(matches, start=1):\n            block_code = match.group(2).strip()\n            block_path = self.source_dir / f\"image_block_{idx:02d}.py\"\n            block_path.write_text(block_code, encoding=\"utf-8\")\n            scene_name = self._extract_scene_name(block_code)\n            await self._emit_progress(\n                f\"Rendering image block {idx}/{len(matches)} with scene `{scene_name}`.\"\n            )\n            await self._run_manim(\n                code_path=block_path,\n                scene_name=scene_name,\n                quality=quality,\n                save_last_frame=True,\n            )\n            image_file = self._find_rendered_file(\".png\")\n            artifact_path = self.artifacts_dir / f\"image-{idx:02d}.png\"","sourceCodeStart":75,"sourceCodeEnd":111,"githubUrl":"https://github.com/HKUDS/DeepTutor/blob/3e82f130422a813cdd73c10b21a44e9325f5821a/deeptutor/agents/math_animator/renderer.py#L75-L111","documentation":"Raised by _extract_text_like when FileTypeRouter.decode_bytes throws while decoding a text-like file (.txt, .md, .py, etc.). Marked 'pragma: no cover' because decode_bytes is designed never to raise (it falls back across encodings), so hitting this indicates an unexpected decoding-layer failure.","triggerScenarios":"Bytes that defeat every fallback encoding in FileTypeRouter.decode_bytes — extremely malformed byte sequences or a decode implementation that raises a non-UnicodeDecodeError (e.g. MemoryError or a LookupError for an unknown codec).","commonSituations":"Essentially unreachable in normal use; would surface only after changes to FileTypeRouter or pathological binary payloads mislabeled with text extensions.","solutions":["Inspect the raw bytes (hexdump) to identify the actual encoding/corruption","Ensure FileTypeRouter.decode_bytes fallbacks are intact if you forked the class","Rename/re-classify the file if it is actually binary with a text extension"],"exampleFix":"// before\ntext = _extract_text_like(data, \"weird.txt\")  # raises\n\n// after\ntext = data.decode(\"utf-8\", errors=\"replace\")  # manual tolerant decode as last resort","handlingStrategy":"try-catch","validationCode":"try:\n    FileTypeRouter.decode_bytes(data)\nexcept Exception:\n    data = data.decode(\"utf-8\", errors=\"replace\").encode(\"utf-8\")  # sanitize","typeGuard":null,"tryCatchPattern":"except CorruptDocumentError as e:\n    if \"failed to decode text\" in str(e):\n        text = data.decode(\"utf-8\", errors=\"replace\")","preventionTips":["Treat text files as untrusted bytes; use replace-on-error decoding as a last resort"],"tags":["encoding","text-decode","defensive"],"backgroundTag":"text-decoding-failure","analyzedSha":"3e82f130422a813cdd73c10b21a44e9325f5821a","analyzedAt":"2026-08-27T06:57:25.364Z","schemaVersion":2},"datasetVersion":"2026-08-27T08:17:20.692Z"}