deepset-ai/haystack · error

Document with ID '{doc.id}' has a file path '{file_path}' th

Error message

Document with ID '{doc.id}' has a file path '{file_path}' that escapes the configured root '{root_path}'. Resolved path: '{resolved_file_path}'.

What it means

As a path-traversal guard, when root_path is configured every resolved file path must remain inside that root. If metadata-controlled paths like '../../etc/passwd' or absolute paths outside the root resolve outside it, the component raises ValueError to prevent reading arbitrary files.

Source

Thrown at haystack/components/converters/image/image_utils.py:260

    for doc in documents:
        file_path = doc.meta.get(file_path_meta_field)
        if file_path is None:
            raise ValueError(
                f"Document with ID '{doc.id}' is missing the '{file_path_meta_field}' key in its metadata."
                f" Please ensure that the documents you are trying to convert have this key set."
            )

        resolved_file_path = Path(root_path, file_path)

        # When root_path is set, ensure the resolved path stays within it to block path-traversal
        # payloads (e.g. "../../etc/passwd") coming from document metadata. When root_path is unset,
        # file paths are treated as absolute by design and no containment check is applied; callers that
        # process untrusted metadata should configure root_path (see component docstrings).
        if root_path:
            resolved_file_path = resolved_file_path.resolve()
            resolved_root = Path(root_path).resolve()
            if not resolved_file_path.is_relative_to(resolved_root):
                raise ValueError(
                    f"Document with ID '{doc.id}' has a file path '{file_path}' that escapes the "
                    f"configured root '{root_path}'. Resolved path: '{resolved_file_path}'."
                )

        if not resolved_file_path.is_file():
            raise ValueError(
                f"Document with ID '{doc.id}' has an invalid file path '{resolved_file_path}'. "
                f"Please ensure that the documents you are trying to convert have valid file paths."
            )

        mime_type = doc.meta.get("mime_type") or mimetypes.guess_type(resolved_file_path)[0]
        if mime_type not in IMAGE_MIME_TYPES:
            raise ValueError(
                f"Document with file path '{resolved_file_path}' has an unsupported MIME type '{mime_type}'. "
                f"Please ensure that the documents you are trying to convert are of the supported "
                f"types: {', '.join(IMAGE_MIME_TYPES)}."
            )

View on GitHub (pinned to e318778c9b)

Solutions

  1. Make file_path relative to root_path (e.g. 'img/doc1.png' with root_path='/data').
  2. Point root_path at a directory that actually contains all referenced files.
  3. Remove '..' segments from stored metadata; re-index documents with corrected paths.
  4. If absolute paths are intended, set root_path to None (paths are then trusted as absolute by design).

Example fix

// before
converter.run(documents=docs, root_path="/data")  # meta file_path="../../etc/image.png"
// after
doc.meta["file_path"] = "images/image.png"  # relative to /data
converter.run(documents=docs, root_path="/data")
Defensive patterns

Strategy: validation

Validate before calling

from pathlib import Path
def ensure_inside_root(root_path, file_path):
    resolved = Path(root_path, file_path).resolve()
    if not resolved.is_relative_to(Path(root_path).resolve()):
        raise ValueError(f"{file_path!r} escapes root {root_path}")

Type guard

def is_safe_relative(file_path: str) -> bool:
    p = Path(file_path)
    return not p.is_absolute() and ".." not in p.parts

Try / catch

try:
    result = converter.run(documents=docs, root_path=root)
except ValueError as e:
    if "escapes the configured root" in str(e):
        logger.error("Rejected untrusted path: %s", e)  # treat as security event, do not retry
        raise
    raise

Prevention

When it happens

Trigger: Document meta file_path containing '..' segments or absolute paths that, after Path(root_path, file_path).resolve(), are not relative to the configured root_path — e.g. meta file_path='/etc/passwd' with root_path='/data'.

Common situations: Documents ingested from untrusted sources carrying absolute paths; mixing storage roots between pipeline stages; symlinks pointing outside the root; moving a pipeline between machines with different data roots.

Related errors


AI-assisted analysis of deepset-ai/haystack@e318778c9b (2026-08-30). Data as JSON: /api/errors/89b2be72b225adf5. Report an issue: GitHub.