BookStackApp/BookStack · error · PdfExportException

PDF Export via command failed due to timeout at {$timeout} s

Error message

PDF Export via command failed due to timeout at {$timeout} second(s)

What it means

Thrown by renderUsingCommand in app/Exports/PdfGenerator.php when the configured external PDF command (exports.pdf_command, run via Symfony Process) exceeds exports.pdf_command_timeout seconds and Symfony aborts it with ProcessTimedOutException. The library cleans up both temp files (HTML input and PDF output) and rethrows as this PdfExportException. It means the external renderer hung or was too slow for the configured limit.

Source

Thrown at app/Exports/PdfGenerator.php:160

        file_put_contents($inputHtml, $html);

        $timeout = intval(config('exports.pdf_command_timeout'));
        $process = Process::fromShellCommandline($command);
        $process->setTimeout($timeout);

        $cleanup = function () use ($inputHtml, $outputPdf) {
            foreach ([$inputHtml, $outputPdf] as $file) {
                if (file_exists($file)) {
                    unlink($file);
                }
            }
        };

        try {
            $process->run();
        } catch (ProcessTimedOutException $e) {
            $cleanup();
            throw new PdfExportException("PDF Export via command failed due to timeout at {$timeout} second(s)");
        }

        if (!$process->isSuccessful()) {
            $cleanup();
            throw new PdfExportException("PDF Export via command failed with exit code {$process->getExitCode()}, stdout: {$process->getOutput()}, stderr: {$process->getErrorOutput()}");
        }

        $pdfContents = file_get_contents($outputPdf);
        $cleanup();

        if ($pdfContents === false) {
            throw new PdfExportException("PDF Export via command failed, unable to read PDF output file");
        } else if (empty($pdfContents)) {
            throw new PdfExportException("PDF Export via command failed, PDF output file is empty");
        }

        return $pdfContents;
    }

View on GitHub (pinned to 18f8469a1c)

Solutions

  1. Increase exports.pdf_command_timeout (e.g. export PDF_COMMAND_TIMEOUT=120 in .env) to a value above the document's real render time.
  2. Run the exact configured command manually against a sample HTML file to find why it hangs (waiting for input, remote assets, missing flags).
  3. Make the command non-interactive: add flags like --no-sandbox / --disable-gpu / --quiet, and avoid commands that prompt on failure.
  4. Remove or lower timeouts on remote resources referenced in the HTML (images/CSS) or ensure the server can reach them, since blocked fetches stall the renderer.
  5. Check for stuck/zombie renderer processes from prior runs (ps aux | grep pdf/wkhtmltopdf) and kill them.

Example fix

// before (.env)
PDF_COMMAND_TIMEOUT=30  # large books exceed 30s

// after
PDF_COMMAND_TIMEOUT=300
Defensive patterns

Strategy: retry

Validate before calling

<?php
// before exporting, sanity-check the command and timeout config
$cmd = config('exports.pdf_command');
$timeout = intval(config('exports.pdf_command_timeout'));
$binary = trim(strtok($cmd, ' '));
$isReady = $cmd && $timeout > 0 && shell_exec('command -v ' . escapeshellarg($binary)) !== null;

Try / catch

try {
    $pdf = $pdfGenerator->fromHtml($html);
} catch (\BookStack\Exceptions\PdfExportException $e) {
    if (str_contains($e->getMessage(), 'failed due to timeout')) {
        // retry with a bigger timeout or queue the export to a background job
        Log::warning('PDF command timed out; consider PDF_COMMAND_TIMEOUT increase');
    }
    throw $e;
}

Prevention

When it happens

Trigger: Calling fromHtml() with exports.pdf_command configured; the shell command (placeholders {input_html_path}/{output_pdf_path} substituted) runs longer than intval(config('exports.pdf_command_timeout')) seconds, e.g. the external tool waits for stdin, blocks on a network resource, or crashes into a hang.

Common situations: Very large/complex documents that genuinely need more time; a misconfigured command that prompts or waits for input; wkhtmltopdf/chromium hanging on remote images with no network access; pdf_command_timeout set too low (or 0/negative causing odd behavior); zombie processes from a previous crashed run holding locks.

Understand the failure class

Related errors


AI-assisted analysis of BookStackApp/BookStack@18f8469a1c (2026-09-02). Data as JSON: /api/errors/b5ede5665fc9a786. Report an issue: GitHub.