ComposioHQ/composio · error · SDKFileNotFoundError

Not a file: {file}. Please provide a valid file path.

Error message

Not a file: {file}. Please provide a valid file path.

What it means

After confirming the path exists, from_path checks is_file() and raises SDKFileNotFoundError when the path is a directory, FIFO, device, or other non-regular file. Regular files are required because the content is read and uploaded.

Source

Thrown at python/composio/core/models/_files.py:645

        # ``None`` to bypass the allowlist (manual upload APIs).
        if file_upload_allowlist is not None:
            assert_path_inside_upload_dirs(path_in, file_upload_allowlist)

        assert_safe_local_file_upload_path(
            path_in,
            enabled=sensitive_file_upload_protection,
            additional_deny_segments=file_upload_path_deny_segments,
        )

        # Handle as local file path
        file = Path(path_in)
        if not file.exists():
            raise SDKFileNotFoundError(
                f"File not found: {file}. Please provide a valid file path."
            )

        if not file.is_file():
            raise SDKFileNotFoundError(
                f"Not a file: {file}. Please provide a valid file path."
            )

        if not os.access(file, os.R_OK):
            raise SDKFileNotFoundError(
                f"File not readable: {file}. Please check the file permissions."
            )

        mimetype = mimetypes.guess(file=file)
        s3meta = _request_presigned_upload(
            client,
            filename=file.name,
            md5=get_md5(file=file),
            mimetype=mimetype,
            tool=tool,
            toolkit=toolkit,
        )
        upload(url=s3meta.new_presigned_url, file=file, mimetype=mimetype)

View on GitHub (pinned to 64b1b85502)

Solutions

  1. Check p.is_file() first and filter out directories in your selection logic.
  2. If you meant to upload multiple files, iterate over p.iterdir() filtering is_file() and upload each.
  3. Fix the path to point at the actual file.

Example fix

# before
file = FileModel.from_path(client, Path('./reports'))  # directory -> raises
# after
for f in sorted(Path('./reports').glob('*')):
    if f.is_file():
        FileModel.from_path(client, f)
Defensive patterns

Strategy: type-guard

Validate before calling

from pathlib import Path

paths = [p for p in Path('./data').glob('*') if p.is_file()]

Type guard

def is_regular_file(p) -> bool:
    from pathlib import Path
    f = Path(p)
    return f.exists() and f.is_file()

Try / catch

from composio.core.models._files import SDKFileNotFoundError

try:
    model = FileModel.from_path(client, p)
except SDKFileNotFoundError as e:
    if 'Not a file' in str(e):
        for child in sorted(Path(p).glob('*')):
            if child.is_file():
                FileModel.from_path(client, child)
    else:
        raise

Prevention

When it happens

Trigger: Passing a directory path or special file (e.g. /dev/null is a file, but a mount point, named pipe, or directory like ./data triggers this) to FileModel.from_path.

Common situations: Globbing that returns directories; passing a folder expecting recursive upload; symlink chains resolving to a directory; accidentally passing a path with a trailing slash on some platforms.

Related errors


AI-assisted analysis of ComposioHQ/composio@64b1b85502 (2026-08-28). Data as JSON: /api/errors/d0e35032529667f1. Report an issue: GitHub.