opendataloader-project/opendataloader-pdf · error · RuntimeError

Conversion completed but no output file was generated.

Error message

Conversion completed but no output file was generated.

What it means

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.

Source

Thrown at python/opendataloader-pdf-mcp/src/opendataloader_pdf_mcp/server.py:161

        if hybrid_url is not None:
            kwargs["hybrid_url"] = hybrid_url
        if hybrid_timeout is not None:
            kwargs["hybrid_timeout"] = hybrid_timeout
        if hybrid_fallback:
            kwargs["hybrid_fallback"] = True
        if image_dir is not None:
            kwargs["image_dir"] = image_dir

        opendataloader_pdf.convert(**kwargs)

        # Find and read the output file
        stem = input_file.stem
        output_file = Path(tmp_dir) / f"{stem}{ext}"

        if not output_file.is_file():
            files = [f for f in Path(tmp_dir).iterdir() if f.is_file()]
            if not files:
                raise RuntimeError(
                    "Conversion completed but no output file was generated."
                )
            matching_ext = sorted(f for f in files if f.suffix == ext)
            if not matching_ext:
                raise RuntimeError(
                    f"Conversion completed but no '{ext}' output file was generated."
                )
            output_file = matching_ext[0]

        return output_file.read_text(encoding="utf-8")


def main():
    """Run the MCP server."""
    mcp.run()


if __name__ == "__main__":

View on GitHub (pinned to a7789b8e77)

Solutions

  1. Run the same conversion via the CLI directly (odl-pdf <file>) outside the MCP server to see the real subprocess stderr/exit code.
  2. If the JVM is OOM-killed, raise the container/process memory limit or pass -Xmx to the JVM.
  3. 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.
  4. Check dmesg/journal for an OOM kill of the java process during conversion.

Example fix

# before: silent empty output, cause hidden
convert(...); # RuntimeError, no clue
# after: run the CLI directly to surface the real error
$ odl-pdf doc.pdf -o /tmp/out
# -> reveals 'java.lang.OutOfMemoryError' or 'jar not found'
Defensive patterns

Strategy: try-catch

Validate before calling

# No pre-check; instead, surface the real subprocess error by running the CLI directly first:
#   odl-pdf <file> -o /tmp/out
# and check exit code + stderr before relying on the MCP wrapper.

Type guard

def is_empty_output_error(exc: RuntimeError) -> bool:
    return isinstance(exc, RuntimeError) and "no output file was generated" in str(exc) and "'" not in str(exc)

Try / catch

try:
    text = convert(input_path=path, format="markdown")
except RuntimeError as e:
    msg = str(e)
    if "no output file was generated" in msg and "'" not in msg:
        # zero files — likely JVM crash/OOM; run the CLI to see real stderr
        import subprocess
        subprocess.run(["odl-pdf", path, "-o", "/tmp/out"], check=True)
    raise

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of opendataloader-project/opendataloader-pdf@a7789b8e77 (2026-08-14). Data as JSON: /api/errors/391edb55aab05335. Report an issue: GitHub.