opendataloader-project/opendataloader-pdf · error · FileNotFoundError

Input file not found: {input_path}

Error message

Input file not found: {input_path}

What it means

FileNotFoundError raised by the MCP convert tool after Path(input_path).expanduser().resolve() when the resolved path is not a regular file. Because expanduser+resolve run first, the message echoes the ORIGINAL input_path (which may differ from the resolved absolute path), and symlinks/relative paths are resolved against the MCP server's cwd.

Source

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

        text_page_separator: Separator between pages in text output.
        html_page_separator: Separator between pages in HTML output.
        image_output: Image output mode. Values: off, embedded, external.
        image_format: Image format. Values: png, jpeg.
        include_header_footer: Include page headers and footers in output.
        detect_strikethrough: Detect strikethrough text (experimental).
        hybrid: Hybrid backend. Values: off, docling-fast.
        hybrid_mode: Hybrid triage mode. Values: auto, full.
        hybrid_url: Hybrid backend server URL.
        hybrid_timeout: Hybrid backend timeout in milliseconds.
        hybrid_fallback: Enable Java fallback on hybrid backend error.
        image_dir: Directory path to save extracted images.

    Returns:
        The converted content as text.
    """
    input_file = Path(input_path).expanduser().resolve()
    if not input_file.is_file():
        raise FileNotFoundError(f"Input file not found: {input_path}")

    # Determine output file extension from format
    ext_map = {
        "json": ".json",
        "text": ".txt",
        "html": ".html",
        "markdown": ".md",
        "markdown-with-html": ".md",
        "markdown-with-images": ".md",
    }
    if format not in ext_map:
        raise ValueError(
            f"Unsupported format: {format!r}. "
            f"Supported formats: {', '.join(ext_map)}"
        )
    ext = ext_map[format]

    with tempfile.TemporaryDirectory() as tmp_dir:

View on GitHub (pinned to a7789b8e77)

Solutions

  1. Send an absolute path to the MCP tool to avoid cwd-dependent resolution.
  2. Verify the file exists from the server's perspective: ensure the path is reachable by the process running the MCP server (mounts, permissions).
  3. Check for typos and the correct extension (.pdf).
  4. If using a symlink, confirm the target exists (readlink -f).

Example fix

# before: relative path resolved from server cwd, not found
convert(input_path="~/reports/q3.pdf")  # '~' expanded but file absent -> error
# after: absolute, verified path
convert(input_path="/home/user/reports/q3.pdf")
Defensive patterns

Strategy: validation

Validate before calling

from pathlib import Path

def ensure_input(input_path: str) -> Path:
    p = Path(input_path).expanduser().resolve()
    if not p.is_file():
        raise FileNotFoundError(f"Input file not found: {input_path}")
    return p

Type guard

def is_valid_input(input_path: str) -> bool:
    try:
        return Path(input_path).expanduser().resolve().is_file()
    except OSError:
        return False

Try / catch

try:
    result = convert(input_path=path, format="markdown")
except FileNotFoundError as e:
    # message echoes the original input_path
    return {"error": str(e), "hint": "send an absolute, verified path"}

Prevention

When it happens

Trigger: Calling the MCP server's convert tool with a path that does not exist on disk, a broken symlink, a path relative to a different cwd than the server runs in, or a path with a typo.

Common situations: Client sends a relative path assuming the user's home, but the server resolves from its own working directory. A path with a typo or wrong extension. An NFS/mount path not available inside the server's container. A deleted file referenced by a stale bookmark.

Related errors


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