vercel/ai · error · DownloadError
Too many redirects (max ${maxRedirects})
Error message
Too many redirects (max ${maxRedirects}) What it means
fetchWithValidatedRedirects caps redirect chains at maxRedirects (default 10) to prevent infinite redirect loops that would exhaust connections or enable DoS. When the chain exceeds the limit, the download is aborted with this DownloadError. Redirect loops are almost always a server- or configuration-side problem, not a client bug.
Source
Thrown at packages/provider-utils/src/fetch-with-validated-redirects.ts:151
// redirect that crosses origin. Only stripping Authorization (as the
// fetch spec does) is not enough on the server: providers authenticate
// with custom headers too (e.g. `x-key`), and without CORS there is
// nothing else stopping them from riding to a foreign host.
if (currentHeaders !== undefined && !isSameOrigin(nextUrl, currentUrl)) {
const userAgent = currentHeaders.get('user-agent');
currentHeaders = new Headers(
userAgent == null ? undefined : { 'user-agent': userAgent },
);
}
currentUrl = nextUrl;
continue;
}
return response;
}
throw new DownloadError({
url,
message: `Too many redirects (max ${maxRedirects})`,
});
}
View on GitHub (pinned to 69428b1f8b)
Solutions
- Follow the URL manually (curl -IL) to inspect the redirect chain and find where it loops.
- Fix the origin: correct http→https or www redirect configuration on the asset host so a single hop reaches the file.
- Use the final, direct asset URL instead of a redirecting short link.
- If the chain is legitimate but long, supply a custom fetch or raise maxRedirects where the API surface allows it.
Example fix
// before: URL bounces forever between http/https
const blob = await downloadBlob('http://cdn.example.com/video.mp4');
// after: use the final https URL directly
const blob = await downloadBlob('https://cdn.example.com/video.mp4'); Defensive patterns
Strategy: validation
Validate before calling
async function countRedirects(url: string, max = 10): Promise<number> {
let hops = 0;
let current = url;
while (hops <= max) {
const res = await fetch(current, { redirect: 'manual' });
const location = res.headers.get('location');
if (!(res.status >= 300 && res.status < 400) || !location) return hops;
current = new URL(location, current).toString();
hops++;
}
throw new Error(`URL exceeds ${max} redirects`);
} Type guard
import { DownloadError } from '@ai-sdk/provider-utils';
function isTooManyRedirects(e: unknown): boolean {
return DownloadError.isInstance(e) && e.message.startsWith('Too many redirects');
} Try / catch
try {
await downloadBlob(url);
} catch (error) {
if (DownloadError.isInstance(error) && error.message.startsWith('Too many redirects')) {
// follow chain with curl -IL, fix the looping origin or use the final URL
}
throw error;
} Prevention
- Trace suspect URLs with curl -IL before relying on them.
- Fix http→https and www redirect loops at the origin/proxy.
- Use final canonical asset URLs instead of redirect chains.
- Remember cross-origin hops drop credentials — auth-gated redirect chains will loop.
When it happens
Trigger: A file/media URL passed to the SDK (via downloadBlob and downstream provider calls) redirects more than 10 times, or two URLs redirect to each other in a loop (e.g. http→https→http, or with/without trailing slash misconfiguration).
Common situations: Misconfigured reverse proxy bouncing between http and https; www vs non-www redirect loops; cookie-gated URLs bouncing between login and asset; CDN misconfiguration; an auth-required URL that keeps redirecting because credentials are stripped on cross-origin hops.
Related errors
- The deepagents harness needs a TCP port exposed by the sandb
- Failed to download ${url}: ${statusCode} ${statusText}
- Failed to download ${url}: ${cause}
- Redirect from ${currentUrl} could not be validated and was b
- Invalid argument for parameter model: model ${model.provider
AI-assisted analysis of vercel/ai@69428b1f8b (2026-08-30).
Data as JSON: /api/errors/e3d832aa9206731a.
Report an issue: GitHub.