ComposioHQ/composio · error · SDKFileNotFoundError

File not readable: {file}. Please check the file permissions

Error message

File not readable: {file}. Please check the file permissions.

What it means

Final pre-upload local check: the path exists and is a regular file, but os.access(file, os.R_OK) fails — the running process lacks read permission — so SDKFileNotFoundError (with a permissions message) is raised.

Source

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

            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)
        return cls(name=file.name, mimetype=mimetype, s3key=s3meta.key)


def _discard_partial_download(outfile: Path) -> None:
    """Remove a half-written download so it is never mistaken for the file.

View on GitHub (pinned to 64b1b85502)

Solutions

  1. chmod +r the file (chmod 644) or chown it to the running user.
  2. In containers, ensure the volume/mount grants read to the app UID, or COPY --chmod.
  3. Copy the file to a readable temp location and upload that.
  4. Run the process as a user with read access.

Example fix

# before (container: file owned by root, app runs as appuser)
file = FileModel.from_path(client, Path('/data/secret.pdf'))  # not readable
# after
# Dockerfile: COPY --chmod=644 secret.pdf /data/secret.pdf
# or at runtime:
import shutil
tmp = Path('/tmp/secret.pdf'); shutil.copy('/data/secret.pdf', tmp)
file = FileModel.from_path(client, tmp)
Defensive patterns

Strategy: validation

Validate before calling

import os
from pathlib import Path

def readable_file(p) -> bool:
    f = Path(p)
    return f.is_file() and os.access(f, os.R_OK)

Type guard

def is_readable_file(p) -> bool:
    import os
    from pathlib import Path
    f = Path(p)
    return f.is_file() and os.access(f, os.R_OK)

Try / catch

from composio.core.models._files import SDKFileNotFoundError

try:
    model = FileModel.from_path(client, p)
except SDKFileNotFoundError as e:
    if 'not readable' in str(e):
        tmp = Path(tempfile.mkstemp()[1])
        shutil.copy(p, tmp)
        model = FileModel.from_path(client, tmp)
    else:
        raise

Prevention

When it happens

Trigger: from_path on a file owned by another user with mode 600/000, files under restrictive ACLs, or container runs where the file is mounted read-denied (root-owned file, non-root process).

Common situations: Docker volumes with root-owned files read by an app user; files created by a service under a different UID; umask/ACL restrictions; NFS exports limiting the client user.

Related errors


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