{"record":{"id":"26b15164935b6d54","repo":"headroomlabs-ai/headroom","slug":"jinja2-is-required-for-report-generation-install","errorCode":null,"errorMessage":"jinja2 is required for report generation. Install with: pip install headroom[reports]","messagePattern":"jinja2 is required for report generation\\. Install with: pip install headroom\\[reports\\]","errorType":"exception","errorClass":"ImportError","httpStatus":null,"severity":"error","filePath":"headroom/reporting/generator.py","lineNumber":23,"sourceCode":"from datetime import datetime\nfrom pathlib import Path\nfrom typing import TYPE_CHECKING, Any\n\nfrom ..storage import create_storage\nfrom ..utils import estimate_cost, format_cost\n\nif TYPE_CHECKING:\n    pass\n\n\ndef _get_jinja2_template(template_str: str):\n    \"\"\"Lazily import jinja2 and create template.\"\"\"\n    try:\n        from jinja2 import Template\n\n        return Template(template_str)\n    except ImportError as e:\n        raise ImportError(\n            \"jinja2 is required for report generation. Install with: pip install headroom[reports]\"\n        ) from e\n\n\n# HTML template embedded as string\nREPORT_TEMPLATE = \"\"\"\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n    <title>Headroom Report - {{ generated_at }}</title>\n    <style>\n        * {\n            box-sizing: border-box;\n            margin: 0;\n            padding: 0;\n        }","sourceCodeStart":5,"sourceCodeEnd":41,"githubUrl":"https://github.com/headroomlabs-ai/headroom/blob/322425c43bffde1ed0b64fecf3cf5951565dd82b/headroom/reporting/generator.py#L5-L41","documentation":"Raised by _get_jinja2_template() in the report generator when the jinja2 import fails while rendering a report. HTML report generation is an optional feature backed by the [reports] extra; the import is lazy so the error appears at render time, not at import of the module.","triggerScenarios":"Calling the report generator's render/generate entry point that builds REPORT_TEMPLATE through _get_jinja2_template() without jinja2 installed.","commonSituations":"Base install of headroom used for proxying only, then someone enables report generation; CI image missing extras; jinja2 removed as a transitive dependency of another package.","solutions":["Install the extra: pip install 'headroom[reports]'.","Check for jinja2 in the deployment image: python -c \"import jinja2\".","Disable report generation in configs for deployments that do not need it."],"exampleFix":"# before\nhtml = generator.render()  # ImportError: jinja2 required\n\n# after\n# pip install 'headroom[reports]'\nhtml = generator.render()","handlingStrategy":"fallback","validationCode":"def jinja2_available() -> bool:\n    try:\n        import jinja2  # noqa: F401\n        return True\n    except ImportError:\n        return False\n\nif not jinja2_available():\n    skip_report_generation()  # or install check in deploy pipeline","typeGuard":"def jinja2_available() -> bool:\n    try:\n        import jinja2  # noqa: F401\n        return True\n    except ImportError:\n        return False","tryCatchPattern":"try:\n    html = generator.render()\nexcept ImportError as e:\n    if 'jinja2' in str(e):\n        logger.warning('reports disabled: %s', e)\n    else:\n        raise","preventionTips":["Include the [reports] extra wherever report generation is enabled.","Gate report generation behind a startup capability probe.","Add 'python -c \"import jinja2\"' to your image build or preflight checks."],"tags":["dependencies","optional-feature","jinja2","reporting","lazy-import"],"backgroundTag":null,"analyzedSha":"322425c43bffde1ed0b64fecf3cf5951565dd82b","analyzedAt":"2026-08-15T01:03:05.481Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}