{"record":{"id":"74cdc9aba3922732","repo":"ATH-MaaS/Pixelle-Video","slug":"template-not-found-template-path","errorCode":null,"errorMessage":"Template not found: {template_path}","messagePattern":"Template not found: (.+?)","errorType":"validation","errorClass":"FileNotFoundError","httpStatus":null,"severity":"error","filePath":"pixelle_video/services/frame_html.py","lineNumber":118,"sourceCode":"                    \"No fonts detected by fontconfig. \"\n                    \"Install fonts with: sudo apt-get install -y fonts-liberation fonts-noto-cjk\"\n                )\n            else:\n                logger.debug(f\"Fontconfig detected {len(result.stdout.splitlines())} fonts\")\n                \n        except FileNotFoundError:\n            logger.warning(\n                \"fontconfig (fc-list) not found on system. \"\n                \"Install with: sudo apt-get install -y fontconfig\"\n            )\n        except Exception as e:\n            logger.debug(f\"Could not check fontconfig status: {e}\")\n    \n    def _load_template(self, template_path: str) -> str:\n        \"\"\"Load HTML template from file\"\"\"\n        path = Path(template_path)\n        if not path.exists():\n            raise FileNotFoundError(f\"Template not found: {template_path}\")\n        \n        with open(path, 'r', encoding='utf-8') as f:\n            content = f.read()\n        \n        logger.debug(f\"Template loaded: {len(content)} chars\")\n        return content\n    \n    def _parse_media_size_from_meta(self) -> tuple[Optional[int], Optional[int]]:\n        \"\"\"\n        Parse media size from meta tags in template\n        \n        Looks for meta tags:\n        - <meta name=\"template:media-width\" content=\"1024\">\n        - <meta name=\"template:media-height\" content=\"1024\">\n        \n        Returns:\n            Tuple of (width, height) or (None, None) if not found\n        \"\"\"","sourceCodeStart":100,"sourceCodeEnd":136,"githubUrl":"https://github.com/ATH-MaaS/Pixelle-Video/blob/848b054e4fae40dabc62ec58e960b573e83793ac/pixelle_video/services/frame_html.py#L100-L136","documentation":"FrameHtmlRenderer._load_template raises FileNotFoundError when the HTML template file passed to the renderer does not exist on disk. It is thrown eagerly in __init__, so constructing the renderer with a bad template path fails immediately, before any rendering work. This guards against silently producing frames from missing templates.","triggerScenarios":"Instantiating the HTML frame renderer (FrameHtmlRenderer.__init__ -> _load_template) with a template_path whose Path.exists() is False: a typo'd filename, a template removed after packaging, a relative path resolved against a different working directory, or a style config pointing at a nonexistent custom template.","commonSituations":"Deploying the app without the bundled template assets; changing CWD so a relative 'templates/frame.html' no longer resolves; renaming templates in a style config (render_style_config) without updating paths; Docker images that .dockerignore the templates directory.","solutions":["Print and verify the template_path exists: python -c \"import os; print(os.path.exists('<path>'))\" and fix typos or missing files.","Convert the template path to an absolute path anchored at the package directory (e.g. Path(__file__).parent / 'templates' / 'frame.html') instead of relying on CWD.","Ensure template assets are included in packaging/deployment (MANIFEST.in / package_data / Dockerfile COPY).","If the template is user-supplied via config, validate the path before constructing the renderer and fall back to the built-in default template."],"exampleFix":"// before\nrenderer = FrameHtmlRenderer(\"templates/frame.html\")\n\n// after\nfrom pathlib import Path\ntemplate = Path(__file__).parent / \"templates\" / \"frame.html\"\nif not template.exists():\n    template = DEFAULT_TEMPLATE_PATH  # bundled fallback\nrenderer = FrameHtmlRenderer(str(template))","handlingStrategy":"validation","validationCode":"from pathlib import Path\ndef ensure_template(path: str) -> str:\n    p = Path(path)\n    if not p.is_file():\n        raise ValueError(f\"Template missing before render: {p.resolve()}\")\n    return str(p)\n\nrenderer = FrameHtmlRenderer(ensure_template(cfg.template_path))","typeGuard":null,"tryCatchPattern":"try:\n    renderer = FrameHtmlRenderer(template_path)\nexcept FileNotFoundError as e:\n    logger.warning(\"template missing (%s), using default\", e)\n    renderer = FrameHtmlRenderer(DEFAULT_TEMPLATE_PATH)","preventionTips":["Always resolve template paths absolutely relative to the package (Path(__file__).parent), never CWD.","Add template files to package data / Docker image and verify in CI that all bundled templates exist.","Validate configured template paths at startup, before the render loop."],"tags":["file-not-found","filesystem","template","python"],"backgroundTag":"file-not-found","analyzedSha":"848b054e4fae40dabc62ec58e960b573e83793ac","analyzedAt":"2026-08-30T03:24:41.468Z","schemaVersion":2},"datasetVersion":"2026-08-30T08:17:16.595Z"}