{"record":{"id":"5e364d7fd903b214","repo":"zylon-ai/private-gpt","slug":"ghostscript-timed-out-for-file-path-name","errorCode":null,"errorMessage":"Ghostscript timed out for {file_path.name}","messagePattern":"Ghostscript timed out for (.+?)","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"private_gpt/components/readers/vision/vision_reader.py","lineNumber":80,"sourceCode":"                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,\n            resolution,\n        )\n        return images\n","sourceCodeStart":62,"sourceCodeEnd":98,"githubUrl":"https://github.com/zylon-ai/private-gpt/blob/4a030776a31a901ad80b1bf4d7faa2c1a367efbb/private_gpt/components/readers/vision/vision_reader.py#L62-L98","documentation":"VisionReader runs Ghostscript with subprocess.run(..., timeout=120); a TimeoutExpired is caught and re-raised as RuntimeError('Ghostscript timed out for <file>') with the original suppressed (`from None`). It means the rasterization did not finish within the hard-coded 120-second budget — typically very large or pathologically complex documents, or an overloaded/starved machine.","triggerScenarios":"Vision ingestion of a document whose Ghostscript rasterization exceeds 120s — thousands of pages, huge page dimensions, complex vector graphics, or a CPU-throttled container slowing gs below its usual speed.","commonSituations":"Bulk-ingesting large scanned PDFs; containers with tight CPU limits where gs is throttled; documents with extremely high-resolution embedded images; shared CI runners under load.","solutions":["Split the document into smaller parts (per-chapter/per-100-pages PDFs) and ingest them separately.","Free up CPU for the worker or raise container CPU limits so gs finishes within budget.","Reduce the render DPI if the pipeline exposes it, cutting rasterization time.","If you control the code, make the 120s timeout configurable (it is hard-coded at vision_reader.py:76) and set a higher value for known-large corpora."],"exampleFix":"# before\n# vision_reader.py (hard-coded)\nresult = subprocess.run(cmd, capture_output=True, timeout=120)\n\n# after\nresult = subprocess.run(cmd, capture_output=True, timeout=settings.transformation.vision_documents.gs_timeout)","handlingStrategy":"retry","validationCode":"from pypdf import PdfReader\n\ndef estimate_render_cost(pdf_path: str) -> int:\n    return len(PdfReader(pdf_path).pages)  # budget ~ pages/sec of gs throughput","typeGuard":null,"tryCatchPattern":"for attempt, chunk in enumerate(split_pdf(pdf, max_pages=200)):\n    try:\n        images.extend(vision_reader.render(chunk))\n    except RuntimeError as e:\n        if \"timed out\" in str(e) and attempt == 0:\n            chunk = split_pdf(chunk, max_pages=50)[0]  # retry smaller\n            continue\n        raise","preventionTips":["Split large PDFs into bounded page counts before vision ingestion.","Give ingestion workers enough CPU so gs finishes within the 120s budget.","Monitor per-file render duration and pre-emptively chunk anything unusually slow."],"tags":["ghostscript","timeout","subprocess","pdf","vision","performance"],"backgroundTag":null,"analyzedSha":"4a030776a31a901ad80b1bf4d7faa2c1a367efbb","analyzedAt":"2026-08-15T03:51:26.951Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}