mastra-ai/mastra · error · WebFetchError
Too many redirects. Maximum is ${MAX_REDIRECTS}.
Error message
Too many redirects. Maximum is ${MAX_REDIRECTS}. What it means
requestUrl follows HTTP 3xx redirects manually, up to MAX_REDIRECTS hops, decrementing redirectsRemaining each time. When a redirect response arrives and no redirect budget remains, the tool throws a WebFetchError because unbounded redirect following is both a hang/infinite-loop risk and an SSRF vector (long chains can be steered toward internal addresses).
Source
Thrown at packages/core/src/tools/builtin/web-fetch.ts:218
const request = requestModule.request(
url,
{
headers: {
'user-agent': 'Mastra Web Fetch Tool/1.0',
accept: 'text/html,text/plain,application/json,application/xml;q=0.9,*/*;q=0.8',
},
lookup: createLookup(),
timeout: TIMEOUT_MS,
},
response => {
void (async () => {
const location = response.headers.location;
if (location && response.statusCode && response.statusCode >= 300 && response.statusCode < 400) {
response.resume();
if (redirectsRemaining <= 0) {
throw new WebFetchError(`Too many redirects. Maximum is ${MAX_REDIRECTS}.`);
}
const nextUrl = parseHttpUrl(new URL(location, url).toString());
if (!nextUrl) {
throw new WebFetchError('Redirect target must use HTTP or HTTPS.');
}
resolve(await requestUrl(nextUrl, redirectsRemaining - 1));
return;
}
const { content, truncated } = await readBody(response);
resolve({
content,
truncated,
status: response.statusCode,
statusText: response.statusMessage,View on GitHub (pinned to 75dd419e61)
Solutions
- Resolve the final URL yourself and pass it directly (e.g. curl -ILs <url> to find the terminal URL, or use a URL-expansion service once).
- Break redirect loops: fix the target server's redirect configuration (avoid http<->https or trailing-slash loops).
- If the content genuinely needs many hops, fetch the intermediate hop(s) with separate webFetch calls.
- For legitimate deep chains, raise MAX_REDIRECTS in a fork/patch of the tool — but confirm each hop stays on public hosts, since the limit is also a safety guard.
Example fix
// before
await webFetchTool.execute({ context: { url: 'https://bit.ly/abc123' } }); // 6+ hop chain
// after: resolve first, then fetch the terminal URL
await webFetchTool.execute({ context: { url: 'https://example.com/final/article' } }); Defensive patterns
Strategy: try-catch
Validate before calling
// Resolve redirect chains ahead of time and fetch only the terminal URL
async function resolveFinalUrl(url: string, max = 5): Promise<string> {
let current = url;
for (let i = 0; i < max; i++) {
const res = await fetch(current, { redirect: 'manual', method: 'HEAD' });
if (res.status < 300 || res.status >= 400) return current;
const loc = res.headers.get('location');
if (!loc) return current;
current = new URL(loc, current).toString();
}
throw new Error('exceeds webFetch redirect limit');
} Try / catch
try {
await webFetchTool.execute({ context: { url } });
} catch (err) {
if (err instanceof Error && /Too many redirects/.test(err.message)) {
// resolve the chain manually and retry once with the terminal URL
const finalUrl = await resolveFinalUrl(url);
return webFetchTool.execute({ context: { url: finalUrl } });
} else throw err;
} Prevention
- Resolve short-link URLs before handing them to the tool.
- Fix redirect loops on servers you control (check http->https and trailing-slash rules).
- Watch for auth flows that bounce between login and target pages.
- Track redirect depth in your own URL pipeline and cap it early.
When it happens
Trigger: Fetching a URL that redirects more than MAX_REDIRECTS times: redirect chains, loops (A -> B -> A), cookie/auth flows redirecting repeatedly, short-link services stacked multiple deep, or misconfigured servers emitting endless 302s.
Common situations: Shortened URLs (bit.ly chains) embedded in agent prompts; expired sessions that keep redirecting to a login page that redirects back; misconfigured hosting where http->https->http loops.
Related errors
- Redirect target must use HTTP or HTTPS.
- Slack OAuth HTTP error: ${tokenResponse.status} ${tokenRespo
- Failed to stream background tasks: ${response.statusText}
- Failed to stream agent builder action: ${response.statusText
- Failed to observe agent builder action stream: ${response.st
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/ec04fd443ad51f4d.
Report an issue: GitHub.