ATH-MaaS/Pixelle-Video · error · RuntimeError

HTML rendering failed: {type(e).__name__}: {e}

Error message

HTML rendering failed: {type(e).__name__}: {e}

What it means

generate_frame wraps its entire HTML-template rendering pipeline in a broad try/except; any exception (browser/playwright launch failure, template syntax error, missing asset, network fetch for images, etc.) is re-raised as RuntimeError with the original exception class name and message chained via `from e`. The underlying cause is preserved in __cause__ and logged with logger.exception.

Source

Thrown at pixelle_video/services/frame_html.py:474

                # local file:// image references are loaded under the same origin.
                fd, tmp_html_path = tempfile.mkstemp(suffix='.html', prefix='pv_frame_')
                with os.fdopen(fd, 'w', encoding='utf-8') as f:
                    f.write(html)
                
                await page.goto(Path(tmp_html_path).as_uri(), wait_until='networkidle')
                await page.screenshot(path=output_path, type='png', omit_background=True)
            finally:
                if page:
                    await page.close()
                if tmp_html_path and os.path.exists(tmp_html_path):
                    os.unlink(tmp_html_path)
            
            logger.info(f"Frame generated: {output_path}")
            return output_path
            
        except Exception as e:
            logger.exception("Failed to render HTML template")
            raise RuntimeError(
                f"HTML rendering failed: {type(e).__name__}: {e}"
            ) from e

View on GitHub (pinned to 848b054e4f)

Solutions

  1. Read the chained cause (e.__cause__) or the logged 'Failed to render HTML template' traceback to identify the real exception type.
  2. If the cause is a browser launch error, run the install step (e.g. `playwright install chromium`) or install required system libraries.
  3. Verify output_path's parent directory exists and is writable before calling generate_frame.
  4. Validate the template and referenced assets (fonts, images) exist and the HTML/CSS is well-formed.
  5. Catch RuntimeError around generate_frame and implement a fallback (e.g. plain-color frame) if rendering is optional.

Example fix

// before
output = renderer.generate_frame(template, data, output_path)  # crashes on any inner error

// after
try:
    output = renderer.generate_frame(template, data, output_path)
except RuntimeError as e:
    logger.error("frame render failed: %r", e.__cause__)
    output = fallback_plain_frame(data, output_path)
Defensive patterns

Strategy: try-catch

Validate before calling

import os
assert os.path.isdir(os.path.dirname(output_path) or "."), "output dir missing"
assert Path(template_path).is_file(), "template missing"
# plus: ensure playwright browser installed once at startup
# from playwright.sync_api import sync_playwright
# with sync_playwright() as p: p.chromium.launch()

Try / catch

try:
    out = renderer.generate_frame(template, data, output_path)
except RuntimeError as e:
    cause = e.__cause__
    logger.error("render failed: %s: %s", type(cause).__name__, cause)
    if isinstance(cause, FileNotFoundError):
        ...  # template/asset missing path
    else:
        ...  # fallback frame or re-raise

Prevention

When it happens

Trigger: Any exception raised inside generate_frame (called from render_frame, _compose_frame_html, render_style_config): headless browser not installed/launchable, template file unreadable, invalid CSS/HTML causing renderer error, output directory not writable, or FileNotFoundError 105 bubbling up from _load_template.

Common situations: Playwright/Chromium not installed in a fresh environment ('Executable doesn't exist'); missing system fonts or assets referenced by the template; rendering in a container lacking sandbox flags; disk-full or permission-denied on output_path.

Related errors


AI-assisted analysis of ATH-MaaS/Pixelle-Video@848b054e4f (2026-08-30). Data as JSON: /api/errors/4a4885967675e431. Report an issue: GitHub.