Comfy-Org/ComfyUI · error · ValueError

Invalid file path: {!r}

Error message

Invalid file path: {!r}

What it means

folder_paths.resolve/annotated path resolution joins the requested name with a base directory (explicit annotation, default_dir, or the input directory) and requires the absolute resolved path to stay within that base via is_within_directory. Any name that escapes the base ('../secrets.env', absolute paths that resolve outside, symlinked traversal via abspath) is rejected as a path-traversal attempt; the name is repr()'d so it cannot inject log lines.

Source

Thrown at folder_paths.py:356

        # byte, and by commonpath() on Windows when the paths are on different
        # drives. In either case the target is not safely within the directory.
        return False


def get_annotated_filepath(name: str, default_dir: str | None=None) -> str:
    name, base_dir = annotated_filepath(name)

    if base_dir is None:
        if default_dir is not None:
            base_dir = default_dir
        else:
            base_dir = get_input_directory()  # fallback path

    filepath = os.path.abspath(os.path.join(base_dir, name))
    # Prevent path traversal: the resolved path must stay within base_dir.
    # repr() the name in the message so a crafted value can't inject log lines.
    if not is_within_directory(base_dir, filepath):
        raise ValueError("Invalid file path: {!r}".format(name))
    return filepath


def exists_annotated_filepath(name) -> bool:
    name, base_dir = annotated_filepath(name)

    if base_dir is None:
        base_dir = get_input_directory()  # fallback path

    filepath = os.path.abspath(os.path.join(base_dir, name))
    # Treat traversal attempts as non-existent rather than probing the filesystem.
    if not is_within_directory(base_dir, filepath):
        return False
    return os.path.exists(filepath)


def add_model_folder_path(folder_name: str, full_folder_path: str, is_default: bool = False) -> None:
    global folder_names_and_paths

View on GitHub (pinned to 1c6d8d45b3)

Solutions

  1. Place the file inside the expected base directory (e.g. input/) and reference it by relative name only
  2. Use the '[subdir]' annotation syntax supported by annotated_filepath instead of '../' traversal
  3. Sanitize user-supplied filenames: reject '..' components and absolute paths before calling the API

Example fix

# before
path = get_annotated_filepath("../../etc/passwd")

# after
path = get_annotated_filepath("my_video.mp4")  # file lives in input/
Defensive patterns

Strategy: type-guard

Validate before calling

import os
name = os.path.normpath(name)
assert not os.path.isabs(name) and ".." not in name.split(os.sep), "traversal-style filename rejected"

Type guard

def is_safe_relative_name(name: str) -> bool:
    n = os.path.normpath(name)
    return not os.path.isabs(n) and ".." not in n.split(os.sep)

Try / catch

try:
    p = get_annotated_filepath(name)
except ValueError:
    # treat as user error: reject input, do not probe alternates
    raise

Prevention

When it happens

Trigger: Passing a filename containing '../' sequences that resolve above base_dir; an absolute path whose normalization lands outside the base; a load-image/load-video widget value containing traversal characters; API prompts with crafted filenames.

Common situations: Manually typed widget values with '../' to reach files elsewhere; workflows referencing files by paths from a different machine's directory layout; security testing of the prompt API.

Related errors


AI-assisted analysis of Comfy-Org/ComfyUI@1c6d8d45b3 (2026-08-14). Data as JSON: /api/errors/c74cc168e042ff2b. Report an issue: GitHub.