{"record":{"id":"9f9e35e87d1ad445","repo":"zylon-ai/private-gpt","slug":"ghostscript-failed-for-file-path-name-stderr-t","errorCode":null,"errorMessage":"Ghostscript failed for {file_path.name}: {stderr_text}","messagePattern":"Ghostscript failed for (.+?): (.+?)","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"private_gpt/components/readers/vision/vision_reader.py","lineNumber":76,"sourceCode":"            cmd = [\n                \"gs\",\n                \"-sDEVICE=png16m\",\n                f\"-o{output_pattern}\",\n                f\"-r{resolution}\",\n                \"-dNOPAUSE\",\n                \"-dBATCH\",\n                str(file_path),\n            ]\n\n            try:\n                result = subprocess.run(cmd, capture_output=True, timeout=120)\n                if result.returncode != 0:\n                    stderr_text = (\n                        result.stderr.decode(\"utf-8\", errors=\"replace\")\n                        if result.stderr\n                        else \"No error output\"\n                    )\n                    raise RuntimeError(\n                        f\"Ghostscript failed for {file_path.name}: {stderr_text}\"\n                    )\n            except subprocess.TimeoutExpired:\n                raise RuntimeError(\n                    f\"Ghostscript timed out for {file_path.name}\"\n                ) from None\n\n            png_files = sorted(temp_path.glob(\"page-*.png\"))\n            for png_file in png_files:\n                pil_image = Image.open(png_file)\n                buffer = io.BytesIO()\n                pil_image.save(buffer, format=\"JPEG\", quality=85, optimize=True)\n                images.append(buffer.getvalue())\n\n        logger.info(\n            \"Rendered %d pages from %s (gs, %ddpi)\",\n            len(images),\n            file_path.name,","sourceCodeStart":58,"sourceCodeEnd":94,"githubUrl":"https://github.com/zylon-ai/private-gpt/blob/4a030776a31a901ad80b1bf4d7faa2c1a367efbb/private_gpt/components/readers/vision/vision_reader.py#L58-L94","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"# before\nimages = vision_reader._render_to_images(Path(\"locked.pdf\"))\n# RuntimeError: Ghostscript failed for locked.pdf: ... password ...\n\n# after\n# shell: qpdf --decrypt locked.pdf unlocked.pdf\nimages = vision_reader._render_to_images(Path(\"unlocked.pdf\"))","handlingStrategy":"try-catch","validationCode":"import shutil, subprocess\n\ndef ghostscript_ready() -> bool:\n    gs = shutil.which(\"gs\")\n    if not gs:\n        return False\n    return subprocess.run([gs, \"--version\"], capture_output=True).returncode == 0","typeGuard":null,"tryCatchPattern":"try:\n    images = vision_reader.render(Path(pdf))\nexcept RuntimeError as e:\n    if \"Ghostscript failed\" in str(e):\n        logger.error(\"Render failed, gs stderr: %s\", e)\n        quarantine(pdf)\n    raise","preventionTips":["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."],"tags":["ghostscript","pdf","subprocess","vision","ingestion"],"backgroundTag":null,"analyzedSha":"4a030776a31a901ad80b1bf4d7faa2c1a367efbb","analyzedAt":"2026-08-15T03:51:26.951Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}