{"record":{"id":"391edb55aab05335","repo":"opendataloader-project/opendataloader-pdf","slug":"conversion-completed-but-no-output-file-was-genera","errorCode":null,"errorMessage":"Conversion completed but no output file was generated.","messagePattern":"Conversion completed but no output file was generated\\.","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"python/opendataloader-pdf-mcp/src/opendataloader_pdf_mcp/server.py","lineNumber":161,"sourceCode":"        if hybrid_url is not None:\n            kwargs[\"hybrid_url\"] = hybrid_url\n        if hybrid_timeout is not None:\n            kwargs[\"hybrid_timeout\"] = hybrid_timeout\n        if hybrid_fallback:\n            kwargs[\"hybrid_fallback\"] = True\n        if image_dir is not None:\n            kwargs[\"image_dir\"] = image_dir\n\n        opendataloader_pdf.convert(**kwargs)\n\n        # Find and read the output file\n        stem = input_file.stem\n        output_file = Path(tmp_dir) / f\"{stem}{ext}\"\n\n        if not output_file.is_file():\n            files = [f for f in Path(tmp_dir).iterdir() if f.is_file()]\n            if not files:\n                raise RuntimeError(\n                    \"Conversion completed but no output file was generated.\"\n                )\n            matching_ext = sorted(f for f in files if f.suffix == ext)\n            if not matching_ext:\n                raise RuntimeError(\n                    f\"Conversion completed but no '{ext}' output file was generated.\"\n                )\n            output_file = matching_ext[0]\n\n        return output_file.read_text(encoding=\"utf-8\")\n\n\ndef main():\n    \"\"\"Run the MCP server.\"\"\"\n    mcp.run()\n\n\nif __name__ == \"__main__\":","sourceCodeStart":143,"sourceCodeEnd":179,"githubUrl":"https://github.com/opendataloader-project/opendataloader-pdf/blob/a7789b8e77dd05e2b8659eb3ea12fc458f80bfb8/python/opendataloader-pdf-mcp/src/opendataloader_pdf_mcp/server.py#L143-L179","documentation":"RuntimeError raised when opendataloader_pdf.convert() returned without throwing, but the temp directory contains NO files at all — neither the expected {stem}{ext} nor any other file. This indicates the underlying conversion produced zero output: the Java process likely exited abnormally (crash, OOM kill) or wrote nothing and returned a success-like exit that the wrapper did not flag.","triggerScenarios":"MCP convert tool runs opendataloader_pdf.convert(**kwargs) into a TemporaryDirectory; on return, Path(tmp_dir).iterdir() yields no files. Happens when the JVM is killed (OOM, SIGKILL in a cgroup), the CLI binary is missing/broken, or convert swallowed a subprocess failure.","commonSituations":"Container memory limit too low so the JVM is OOM-killed mid-conversion on a large PDF. The packaged JAR is missing or corrupt so the CLI exits immediately without writing output. A misconfigured JAVA_HOME/CLI path invoking the wrong binary.","solutions":["Run the same conversion via the CLI directly (odl-pdf <file>) outside the MCP server to see the real subprocess stderr/exit code.","If the JVM is OOM-killed, raise the container/process memory limit or pass -Xmx to the JVM.","Verify the JAR is present and valid (the Python package's bundled jar); reinstall the package if the build hook (hatch_build.py) failed to copy it.","Check dmesg/journal for an OOM kill of the java process during conversion."],"exampleFix":"# before: silent empty output, cause hidden\nconvert(...); # RuntimeError, no clue\n# after: run the CLI directly to surface the real error\n$ odl-pdf doc.pdf -o /tmp/out\n# -> reveals 'java.lang.OutOfMemoryError' or 'jar not found'","handlingStrategy":"try-catch","validationCode":"# No pre-check; instead, surface the real subprocess error by running the CLI directly first:\n#   odl-pdf <file> -o /tmp/out\n# and check exit code + stderr before relying on the MCP wrapper.","typeGuard":"def is_empty_output_error(exc: RuntimeError) -> bool:\n    return isinstance(exc, RuntimeError) and \"no output file was generated\" in str(exc) and \"'\" not in str(exc)","tryCatchPattern":"try:\n    text = convert(input_path=path, format=\"markdown\")\nexcept RuntimeError as e:\n    msg = str(e)\n    if \"no output file was generated\" in msg and \"'\" not in msg:\n        # zero files — likely JVM crash/OOM; run the CLI to see real stderr\n        import subprocess\n        subprocess.run([\"odl-pdf\", path, \"-o\", \"/tmp/out\"], check=True)\n    raise","preventionTips":["Raise the container/process memory limit if the JVM is OOM-killed on large PDFs.","Verify the bundled JAR exists and is valid before serving requests.","Smoke-test conversion with the CLI directly to capture subprocess stderr the MCP wrapper hides."],"tags":["mcp","subprocess","empty-output","oom","runtime","python"],"backgroundTag":null,"analyzedSha":"a7789b8e77dd05e2b8659eb3ea12fc458f80bfb8","analyzedAt":"2026-08-14T05:22:03.953Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}