ComposioHQ/composio · error · ErrorDownloadingFile

Error downloading file

Error message

Error downloading file: {_sanitize_url_for_logging(self.s3url)}. Error: {type(e).__name__}

What it means

The GET to the file's S3 URL during download raised a requests RequestException (connection error, DNS failure, TLS problem, timeout at transport level). The error type name and sanitized URL are reported.

Solutions

  1. Verify the s3url host is reachable from the runtime (curl -I).
  2. Retry the download — transient errors are common.
  3. Fix proxy/TLS configuration if a middlebox is interfering.
  4. Check DNS resolution for the bucket host.

Example fix

# before
path = model.download()
# after
from tenacity import retry, wait_exponential, stop_after_attempt
@retry(wait=wait_exponential(multiplier=1), stop=stop_after_attempt(4))
def safe_download():
    return model.download()
path = safe_download()
Defensive patterns

Strategy: retry

Validate before calling

import socket
from urllib.parse import urlparse

def s3_reachable(url: str) -> bool:
    host = urlparse(url).hostname or ''
    try:
        socket.create_connection((host, 443), timeout=5).close()
        return True
    except OSError:
        return False

Try / catch

from composio.core.models._files import ErrorDownloadingFile

for attempt in range(3):
    try:
        path = model.download()
        break
    except ErrorDownloadingFile as e:
        if attempt == 2:
            raise
        time.sleep(2 ** attempt)

Prevention

When it happens

Trigger: FileModel.download when the runtime cannot reach the S3/CDN host of model.s3url — network outage, egress firewall, proxy blocking object storage, expired DNS.

Common situations: Restricted CI/container networks blocking *.amazonaws.com or the CDN; transient connectivity blips; misconfigured HTTPS_PROXY; air-gapped environments.

Related errors


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

Appendix: source

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

            streamed byte count is authoritative because ``Content-Length`` can
            be absent or dishonest.
        """
        # SEC-316: `self.name` also comes from the (potentially compromised or
        # MITM'd) API response. Collapsed to a bare filename and checked against
        # `root` — not `outdir` — so a name like `output_evil/foo`
        # (sibling-prefix attack) is rejected too.
        try:
            outfile = secure_basename_join(outdir, self.name, root=root)
        except UnsafePathComponentError as e:
            raise ErrorDownloadingFile(str(e)) from e
        try:
            response = safe_get(
                self.s3url,
                stream=True,
                timeout=(_CONNECT_TIMEOUT, _READ_TIMEOUT),
            )
        except requests.exceptions.RequestException as e:
            raise ErrorDownloadingFile(
                "Error downloading file: "
                f"{_sanitize_url_for_logging(self.s3url)}. Error: {type(e).__name__}"
            ) from e
        if response.status_code != 200:
            response.close()
            raise ErrorDownloadingFile(
                f"Error downloading file: {_sanitize_url_for_logging(self.s3url)}"
            )

        # Early abort for a self-declared oversized body. The header is only a
        # hint — `parse_content_length` returns None for anything untrustworthy
        # and the streaming counter below is the authoritative limit.
        content_length = parse_content_length(response.headers.get("Content-Length"))
        if content_length is not None and content_length > max_size:
            response.close()
            raise ResponseTooLargeError(
                f"File size ({content_length} bytes) exceeds maximum allowed "
                f"size ({max_size} bytes)"

View on GitHub (pinned to 64b1b85502)