ComposioHQ/composio · error · ErrorDownloadingFile
Error downloading file: {_sanitize_url_for_logging(self.s3ur
Error message
Error downloading file: {_sanitize_url_for_logging(self.s3url)} What it means
The download GET completed but returned a non-200 status. Since presigned S3 URLs are short-lived, the most common cause is an expired or already-consumed URL; other 4xx/5xx indicate missing permissions or origin issues. Only the sanitized URL is shown.
Source
Thrown at python/composio/core/models/_files.py:728
# (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)"
)
total_bytes = 0
try:
# Only once the fetch is validated and connected, so a blocked URL
# leaves no directory behind — and inside the `try`, so a failureView on GitHub (pinned to 64b1b85502)
Solutions
- Re-fetch a fresh FileModel (re-request the file/output from the API) so a new presigned URL is issued, then download promptly.
- Download soon after obtaining the model rather than caching it long-term.
- Check system clock sync (NTP) since signature windows are time-based.
- If persistent, verify bucket/permission changes with Composio support.
Example fix
# before model = get_model_now() # ... hours later ... model.download() # non-200: expired presigned URL # after model = get_model_now() # fresh model -> fresh presigned URL model.download() # download immediately
Defensive patterns
Strategy: retry
Try / catch
from composio.core.models._files import ErrorDownloadingFile
try:
path = model.download()
except ErrorDownloadingFile as e:
model = refresh_model(model.id) # re-fetch -> fresh presigned URL
path = model.download() Prevention
- Download immediately after obtaining a FileModel; don't cache models with s3url for long periods.
- On failure, re-request the model rather than retrying the same URL.
- Keep server clocks NTP-synced to avoid signature-window issues.
When it happens
Trigger: Calling FileModel.download on a model whose s3url presigned link has expired (issued long before), was single-use and already consumed, or the signature no longer matches. Also origin 5xx errors.
Common situations: Holding FileModel objects for a long time before downloading; retrying after a partial download that consumed the one-time URL; clock skew; bucket policy changes.
Related errors
- Error downloading file: {_sanitize_url_for_logging(self.s3ur
- Response size exceeds maximum allowed size ({max_size} bytes
- Unsafe path component: {e}
- Failed to download file: {message} (status_code, status_text
- Failed to upload file to S3: ${uploadResponse.statusText}
AI-assisted analysis of ComposioHQ/composio@64b1b85502 (2026-08-28).
Data as JSON: /api/errors/b832c3fe90a06773.
Report an issue: GitHub.