zylon-ai/private-gpt · error · RuntimeError
Ghostscript failed for {file_path.name}: {stderr_text}
Error message
Ghostscript failed for {file_path.name}: {stderr_text} What it means
VisionReader shells out to Ghostscript (gs) with a 120s timeout to rasterize a document (e.g. PDF) to PNG pages; if the subprocess exits non-zero, the reader raises RuntimeError including the file name and Ghostscript's stderr text. The stderr payload is the actual diagnosis — common causes are a missing/corrupt input file, an unsupported or encrypted PDF, or a broken Ghostscript installation.
Source
Thrown at private_gpt/components/readers/vision/vision_reader.py:76
cmd = [
"gs",
"-sDEVICE=png16m",
f"-o{output_pattern}",
f"-r{resolution}",
"-dNOPAUSE",
"-dBATCH",
str(file_path),
]
try:
result = subprocess.run(cmd, capture_output=True, timeout=120)
if result.returncode != 0:
stderr_text = (
result.stderr.decode("utf-8", errors="replace")
if result.stderr
else "No error output"
)
raise RuntimeError(
f"Ghostscript failed for {file_path.name}: {stderr_text}"
)
except subprocess.TimeoutExpired:
raise RuntimeError(
f"Ghostscript timed out for {file_path.name}"
) from None
png_files = sorted(temp_path.glob("page-*.png"))
for png_file in png_files:
pil_image = Image.open(png_file)
buffer = io.BytesIO()
pil_image.save(buffer, format="JPEG", quality=85, optimize=True)
images.append(buffer.getvalue())
logger.info(
"Rendered %d pages from %s (gs, %ddpi)",
len(images),
file_path.name,View on GitHub (pinned to 4a030776a3)
Solutions
- Read the stderr text in the message — it identifies the exact Ghostscript failure (e.g. 'This file requires a password', 'unreadable file').
- Test the file manually: `gs -dNOPAUSE -dBATCH -sDEVICE=png16m -r<dpi> -o out-%d.png file.pdf`.
- Ensure Ghostscript is installed and on PATH (`gs --version`) inside the container/host running ingestion.
- For encrypted PDFs, decrypt (qpdf --decrypt) or exclude them from vision ingestion.
Example fix
# before
images = vision_reader._render_to_images(Path("locked.pdf"))
# RuntimeError: Ghostscript failed for locked.pdf: ... password ...
# after
# shell: qpdf --decrypt locked.pdf unlocked.pdf
images = vision_reader._render_to_images(Path("unlocked.pdf")) Defensive patterns
Strategy: try-catch
Validate before calling
import shutil, subprocess
def ghostscript_ready() -> bool:
gs = shutil.which("gs")
if not gs:
return False
return subprocess.run([gs, "--version"], capture_output=True).returncode == 0 Try / catch
try:
images = vision_reader.render(Path(pdf))
except RuntimeError as e:
if "Ghostscript failed" in str(e):
logger.error("Render failed, gs stderr: %s", e)
quarantine(pdf)
raise Prevention
- Include the ghostscript package in the ingestion image and check `gs --version` at startup.
- Pre-screen PDFs for encryption (e.g. pypdf is_encrypted) before vision ingestion.
- Surface Ghostscript stderr in monitoring so root causes are visible.
When it happens
Trigger: Ingesting a document through VisionReader where `gs` returns a non-zero exit code — encrypted/password-protected PDFs, malformed PDFs, missing gs binary producing a shell error, or output-path permission issues.
Common situations: Password-protected PDF exports; corrupt/truncated PDF downloads; containers without the ghostscript package installed or not on PATH; a full or read-only temp directory; version mismatch between gs and the PDF's features.
Related errors
- Ghostscript timed out for {file_path.name}
- VisionReaderFactory requires additional dependencies that ar
- Invalid system item in list (dict): {item}
- Invalid system item in list: {item}
- Invalid system specification: {system}
AI-assisted analysis of zylon-ai/private-gpt@4a030776a3 (2026-08-15).
Data as JSON: /api/errors/9f9e35e87d1ad445.
Report an issue: GitHub.