crewAIInc/crewAI · error · ValueError

Too many redirects while fetching URL: {url}

Error message

Too many redirects while fetching URL: {url}

What it means

safe_get() in crewai_tools follows redirects manually so each hop can be re-validated for SSRF. Once the number of followed redirects reaches max_redirects and the response is still a redirect (status in _REDIRECT_STATUS_CODES with a Location header), this ValueError is raised and the response is closed. It is a circuit breaker against redirect loops and chains that are too long.

Source

Thrown at lib/crewai-tools/src/crewai_tools/security/safe_requests.py:78

    current_url = validate_url(url)
    request_kwargs = {**kwargs, "allow_redirects": False}
    timeout = request_kwargs.pop("timeout", 30)
    history: list[requests.Response] = []
    redirects_followed = 0

    try:
        while True:
            response = requests.get(current_url, timeout=timeout, **request_kwargs)
            if (
                response.status_code not in _REDIRECT_STATUS_CODES
                or "Location" not in response.headers
            ):
                response.history = history
                return response

            if redirects_followed >= max_redirects:
                response.close()
                raise ValueError(f"Too many redirects while fetching URL: {url}")

            location = response.headers.get("Location")
            if not location:
                response.history = history
                return response

            try:
                redirect_url = validate_url(urljoin(response.url, location))
            except ValueError:
                response.close()
                raise

            if not _same_origin(current_url, redirect_url):
                request_kwargs = _strip_cross_origin_credentials(request_kwargs)

            history.append(response)
            current_url = redirect_url
            redirects_followed += 1

View on GitHub (pinned to 754d7323be)

Solutions

  1. Raise max_redirects in the safe_get()/fetch_url_body() call if the chain is legitimate but long.
  2. curl -sIL <url> (or a requests session with allow_redirects) to trace the hop chain and find where the loop occurs.
  3. Fix or report the redirect loop on the originating server (commonly an http<->https or trailing-slash rewrite loop).
  4. Use the final URL from a manual trace and request it directly to skip the chain.

Example fix

// before
resp = safe_get(url)  # default max_redirects

// after
resp = safe_get(url, max_redirects=20)
Defensive patterns

Strategy: retry

Try / catch

try:
    resp = safe_get(url)
except ValueError as e:
    if "Too many redirects" in str(e):
        resp = safe_get(url, max_redirects=25)  # one bounded retry with a higher cap
    else:
        raise

Prevention

When it happens

Trigger: Calling safe_get()/fetch_url_body() with default max_redirects on a URL whose server redirects in a cycle (A->B->A), a chain longer than the limit, or a server that always answers 301/302 with a new Location regardless of client behavior.

Common situations: Misconfigured web servers with rewrite loops; CDN/auth layers that append tokens and bounce repeatedly; picking up shortener chains that nest several levels deep; lowering max_redirects below the chain length of a legitimate site.

Related errors


AI-assisted analysis of crewAIInc/crewAI@754d7323be (2026-08-15). Data as JSON: /api/errors/ab65f85997d5d9d7. Report an issue: GitHub.