ComposioHQ/composio · error · ValidationError

URL returned redirect. Please provide a direct URL to the fi

Error message

URL returned redirect. Please provide a direct URL to the file.

What it means

The URL fetcher refuses to follow redirects when downloading a file for upload — if the server responds with a redirect status, this ValidationError tells you to supply the final direct URL. This avoids ambiguous/looping redirects and matches strict fetch behavior.

Source

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

                    size_detail="Response size exceeds maximum allowed size"
                )
            chunks.append(chunk)
    response.close()

    mimetype = response.headers.get("content-type", "application/octet-stream")
    mimetype = mimetype.split(";")[0].strip()
    return b"".join(chunks), mimetype


def _fetch_from_url(url: str) -> t.Tuple[bytes, str]:
    """Fetch file content from a user-supplied URL. Returns (content, mimetype)."""
    try:
        return _fetch_url_bytes(url)
    except _UrlFetchError as e:
        if e.cause is not None:
            raise ValidationError(f"Failed to fetch file from URL: {e.cause}") from e
        if e.redirected:
            raise ValidationError(
                "URL returned redirect. Please provide a direct URL to the file."
            ) from e
        if e.status_code is not None:
            raise ValidationError(
                f"Failed to fetch file from URL: {e.status_code} {e.status_text}"
            ) from e
        raise ValidationError(str(e)) from e


class RemoteFile:
    """Represents a file stored in a tool router session's file mount.

    Provides methods to fetch, save, and work with the file content.
    """

    def __init__(
        self,
        *,

View on GitHub (pinned to 64b1b85502)

Solutions

  1. Resolve the redirect yourself first (curl -sIL -o /dev/null -w '%{url_effective}') and pass the final URL
  2. Use the direct-download variant (e.g. Dropbox ?dl=1, Drive export=download links)
  3. Download locally and upload the bytes/path instead

Example fix

# before
files.add(url='https://www.dropbox.com/s/abc/file.pdf?dl=0')

# after
files.add(url='https://www.dropbox.com/s/abc/file.pdf?dl=1')
# or resolve final URL via HEAD and pass that
Defensive patterns

Strategy: validation

Validate before calling

import requests
r = requests.head(url, allow_redirects=False)
if r.is_redirect:
    url = r.headers['Location']  # resolve once, then pass final URL

Prevention

When it happens

Trigger: Passing links that 30x-redirect: Google Drive share links, Dropbox ?dl=0 pages, S3 presigned URLs that redirect to another region host, shortlinks.

Common situations: Copy-pasting sharing URLs from cloud drives instead of direct-download links.

Related errors


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