srbhr/Resume-Matcher · error · PDFRenderError

PDF rendering failed. Please try again, or try a simpler res

Error message

PDF rendering failed. Please try again, or try a simpler resume or a different template.

What it means

Catch-all PDFRenderError raised by _raise_playwright_error for any PlaywrightError that is neither a missing executable nor connection-refused. The raw Playwright message (which can contain internal navigation URLs and a full call log) is logged server-side; the client gets a generic message to avoid leaking internals and overflowing the error modal.

Source

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

        raise PDFRenderError(
            "Playwright browser executable is missing or out of date. "
            "Command shown for reference; quote the path if it contains spaces: "
            f"{command}"
        ) from error
    if "net::ERR_CONNECTION_REFUSED" in error_msg:
        raise PDFRenderError(
            f"Cannot connect to frontend for PDF generation. "
            f"Attempted URL: {url}. "
            f"Please ensure: 1) The frontend is running, "
            f"2) The FRONTEND_BASE_URL environment variable in the backend .env file "
            f"matches the URL where your frontend is accessible."
        ) from error
    # Catch-all: the raw Playwright message can carry internal navigation URLs
    # and a full call log. Log it server-side; return a generic message to the
    # client (CLAUDE.md rule 5 — and it stops the verbose trace from overflowing
    # the client error modal, #811).
    logger.error("PDF rendering failed for %s: %s", url, error_msg)
    raise PDFRenderError(
        "PDF rendering failed. Please try again, or try a simpler resume or a "
        "different template."
    ) from error


def _loop_supports_subprocess() -> bool:
    if sys.platform != "win32":
        return True
    try:
        loop = asyncio.get_running_loop()
    except RuntimeError:
        return True
    return loop.__class__.__name__ == "ProactorEventLoop"


async def close_pdf_renderer() -> None:
    """Close the Playwright browser instance."""
    global _playwright, _browser

View on GitHub (pinned to 116f9cc3b0)

Solutions

  1. Check backend logs for the full server-side error (logger.error records the raw Playwright message)
  2. Retry the request — transient crashes/timeouts often succeed on a second attempt
  3. Simplify the resume content or switch to a simpler template to reduce render cost
  4. Increase Playwright timeouts / page.goto wait settings if renders are consistently slow
  5. Raise container memory limits or run renders in a queue to reduce concurrent Chromium load
Defensive patterns

Strategy: try-catch

Validate before calling

def is_generic_render_failure(err: Exception) -> bool:
    msg = str(err)
    return not ("Executable doesn't exist" in msg or "net::ERR_CONNECTION_REFUSED" in msg)

Try / catch

try:
    pdf = await render_resume_pdf(url, selector)
except PDFRenderError as e:
    if "PDF rendering failed" in str(e):
        show_user_toast("PDF render failed — try again or simplify the resume")
    else:
        raise

Prevention

When it happens

Trigger: render_resume_pdf's Playwright call raises any other PlaywrightError — e.g. navigation timeout, page crash, renderer OOM, target closed, or an extremely large/complex resume exceeding rendering limits.

Common situations: Very large resumes or heavy templates timing out the default navigation timeout; headless Chromium crashing in memory-constrained containers; SSL/other navigation failures; transient driver crashes under concurrent PDF renders.

Related errors


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