srbhr/Resume-Matcher · error · PDFRenderError

PDF renderer failed to initialize.

Error message

PDF renderer failed to initialize.

What it means

PDFRenderError raised in render_resume_pdf when the module-level lazy-initialized `_browser` is still None after the init path ran, meaning the renderer never successfully started. It guards the render call against using an uninitialized Playwright browser instance.

Source

Thrown at apps/backend/app/pdf.py:333

        try:
            await init_pdf_renderer()
        except NotImplementedError:
            async with _subprocess_lock:
                _subprocess_supported = False
            subprocess_supported = False
        except PlaywrightError as e:
            _raise_playwright_error(e, url)

    if not subprocess_supported:
        try:
            return await _render_resume_pdf_in_thread(
                url, selector, pdf_format, pdf_margins
            )
        except PlaywrightError as e:
            _raise_playwright_error(e, url)

    if _browser is None:
        raise PDFRenderError("PDF renderer failed to initialize.")

    try:
        return await _render_with_browser(_browser, url, selector, pdf_format, pdf_margins)
    except PlaywrightError as e:
        _raise_playwright_error(e, url)

View on GitHub (pinned to 116f9cc3b0)

Solutions

  1. Check earlier server logs for the underlying Playwright launch failure (missing executable, launch timeout)
  2. Run `<python> -m playwright install chromium` in the deployment environment
  3. Restart the backend so lazy init retries on the next request
  4. Add retry/init-failure propagation around the browser initialization step
  5. Ensure only the app's event loop policy allows subprocesses (_loop_supports_subprocess) so init can run on Windows
Defensive patterns

Strategy: retry

Validate before calling

from app import pdf
def renderer_ready() -> bool:
    return pdf._browser is not None

Try / catch

try:
    pdf_bytes = await render_resume_pdf(url, selector)
except PDFRenderError as e:
    if str(e) == "PDF renderer failed to initialize.":
        await asyncio.sleep(1)
        pdf_bytes = await render_resume_pdf(url, selector)  # retry re-runs lazy init
    else:
        raise

Prevention

When it happens

Trigger: render_resume_pdf is called but `_browser` remains None because the lazy init (get/launch browser) failed or was skipped, and the failure path didn't already raise a more specific error.

Common situations: First PDF request arriving before/while browser initialization failed; Playwright runtime missing browsers in a fresh deploy; init exception swallowed in the init helper; concurrent requests racing an in-progress init that failed.

Related errors


AI-assisted analysis of srbhr/Resume-Matcher@116f9cc3b0 (2026-08-28). Data as JSON: /api/errors/50e32abcb8724a4b. Report an issue: GitHub.