ComposioHQ/composio · error · RemoteFileDownloadError

Failed to download file: {message} (status_code, status_text

Error message

Failed to download file: {message} (status_code, status_text, download_url, mount_relative_path, filename)

What it means

RemoteFileDownloadError raised when lazily downloading a previously uploaded session file via .buffer() (called by .text()/.save()). It enriches a failed fetch with structured fields — status_code, status_text, download_url, mount_relative_path, filename — and a message derived from the status, the exception type name, or the error string.

Source

Thrown at python/composio/core/models/tool_router_session_files.py:215

        :func:`_fetch_url_bytes` — the same body that serves user-supplied
        URLs — rather than a bare ``requests.get``: which side of the trust
        boundary the URL arrived from does not change what the fetch needs to
        defend against.
        """
        try:
            content, _ = _fetch_url_bytes(self.download_url)
        except _UrlFetchError as e:
            if e.redirected:
                message = (
                    "Failed to download file: the download URL returned a redirect"
                )
            elif e.status_code is not None:
                message = f"Failed to download file: {e.status_code} {e.status_text}"
            elif e.cause is not None:
                message = f"Failed to download file: {type(e.cause).__name__}"
            else:
                message = f"Failed to download file: {e}"
            raise RemoteFileDownloadError(
                message,
                status_code=e.status_code,
                status_text=e.status_text,
                download_url=self.download_url,
                mount_relative_path=self.mount_relative_path,
                filename=self.filename,
            ) from (e.cause or e)
        return content

    def text(self) -> str:
        """Fetch the file content as UTF-8 text."""
        return self.buffer().decode("utf-8")

    def save(self, path: t.Optional[t.Union[str, Path]] = None) -> str:
        """Download and save the file to the local filesystem.

        Returns the absolute path where the file was saved.
        If path is omitted, saves to ~/.composio/files/ using the filename.

View on GitHub (pinned to 64b1b85502)

Solutions

  1. Inspect e.status_code/e.download_url to identify expiry (403) vs missing (404)
  2. Re-download promptly after upload/session creation before link expiry
  3. If expired, re-upload or re-create the session to obtain fresh URLs

Example fix

# before
data = remote_file.buffer()

# after
try:
    data = remote_file.buffer()
except RemoteFileDownloadError as e:
    if e.status_code == 403:
        raise RuntimeError('download link expired; re-create session') from e
    raise
Defensive patterns

Strategy: try-catch

Try / catch

from composio.core.models.tool_router_session_files import RemoteFileDownloadError
try:
    data = remote_file.buffer()
except RemoteFileDownloadError as e:
    if e.status_code == 403:
        data = refetch_or_recreate()
    else:
        raise

Prevention

When it happens

Trigger: Calling remote_file.buffer()/text()/save() after the file's download_url expired or was revoked, or when the storage host is unreachable/timeouts. Tests exercise success, generic failure, timeout, and download_url validation of exactly this path.

Common situations: Reading file contents long after the session ended and presigned storage links expired; network egress blocked from the runtime.

Related errors


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