{"record":{"id":"2382b175c2347ad2","repo":"ocrmypdf/OCRmyPDF","slug":"ran-program-program-but-it-exited-with-an-erro","errorCode":null,"errorMessage":"Ran program '{program}' but it exited with an error:\n{e.output}","messagePattern":"Ran program '(.+?)' but it exited with an error:\n(.+?)","errorType":"exception","errorClass":"MissingDependencyError","httpStatus":null,"severity":"error","filePath":"src/ocrmypdf/subprocess/_version.py","lineNumber":58,"sourceCode":"    try:\n        proc = _sp.run(\n            args_prog,\n            close_fds=True,\n            text=True,\n            stdout=PIPE,\n            stderr=STDOUT,\n            check=True,\n            env=env,\n        )\n        output: str = proc.stdout\n    except FileNotFoundError as e:\n        raise MissingDependencyError(\n            f\"Could not find program '{program}' on the PATH\"\n        ) from e\n    except CalledProcessError as e:\n        if e.returncode != 0:\n            log.exception(e)\n            raise MissingDependencyError(\n                f\"Ran program '{program}' but it exited with an error:\\n{e.output}\"\n            ) from e\n        raise MissingDependencyError(\n            f\"Could not find program '{program}' on the PATH\"\n        ) from e\n\n    # Some tools (e.g. veraPDF launched on a recent JDK) print warnings before\n    # the version line, so scan each line rather than only the start of output.\n    version = None\n    for line in output.splitlines():\n        match = re.match(regex, line.strip())\n        if match:\n            version = match.group(1)\n            break\n    if version is None:\n        raise MissingDependencyError(\n            f\"The program '{program}' did not report its version. \"\n            f\"Message was:\\n{output}\"","sourceCodeStart":40,"sourceCodeEnd":76,"githubUrl":"https://github.com/ocrmypdf/OCRmyPDF/blob/5074a0b0e109362422b768fd271ed84bf717c4ec/src/ocrmypdf/subprocess/_version.py#L40-L76","documentation":"The version-check subprocess ran but exited non-zero, so the tool exists but failed when asked for its version. The tool's output is embedded in the message.","triggerScenarios":"get_version(program) where Popen succeeds but the process exits with returncode != 0 — e.g. a broken install, missing shared libraries, or a tool that errors on the version flag used.","commonSituations":"Half-installed packages, missing runtime libs (libtesseract, ghostscript libs), sandboxed environments where the binary crashes, or a wrong --version argument expectation for a custom tool.","solutions":["Run the exact failing command manually (e.g. `qpdf --version`) to see the real error","Fix the underlying crash: reinstall the package or install missing shared libraries (ldd /usr/bin/tesseract)","If it's a custom plugin tool, ensure it supports the version flag passed to get_version"],"exampleFix":"# before\nv = get_version('mytool', args=['--version'], regex=r'mytool v(.*)')\n# after\nimport subprocess\nout = subprocess.run(['mytool', '--version'], capture_output=True, text=True)\n# inspect out.returncode/out.stderr, fix install, then call get_version","handlingStrategy":"try-catch","validationCode":"import subprocess\\nr = subprocess.run([program, '--version'], capture_output=True, text=True)\\nassert r.returncode == 0, r.stderr","typeGuard":null,"tryCatchPattern":"try:\\n    v = get_version(program, regex=...)\\nexcept MissingDependencyError as e:\\n    if 'exited with an error' in str(e):\\n        fix_tool_install(program)  # reinstall / install libs\\n    raise","preventionTips":["Smoke-test external tools' --version in deployment health checks","Install missing shared libraries (ldd) when tools crash on startup","Pin known-good tool versions in your environment"],"tags":["dependency","subprocess","external-tool","version-check"],"backgroundTag":"subprocess-nonzero-exit","analyzedSha":"5074a0b0e109362422b768fd271ed84bf717c4ec","analyzedAt":"2026-08-27T11:57:38.523Z","schemaVersion":2},"datasetVersion":"2026-08-27T13:17:12.746Z"}