tsenart/vegeta · warning
stopped after %d redirects
Error message
stopped after %d redirects
What it means
When an attack is configured with MaxRedirects(n) where n != NoFollow, vegeta installs an http.Client.CheckRedirect that returns this error once the redirect chain exceeds n requests. It is a deliberate policy limit, not an internal failure — the attack records it and continues with subsequent requests.
Source
Thrown at lib/attack.go:149
}
// ChunkedBody returns a functional option which makes the attacker send the
// body of each request with the chunked transfer encoding.
func ChunkedBody(b bool) func(*Attacker) {
return func(a *Attacker) { a.chunked = b }
}
// Redirects returns a functional option which sets the maximum
// number of redirects an Attacker will follow.
func Redirects(n int) func(*Attacker) {
return func(a *Attacker) {
a.redirects = n
a.client.CheckRedirect = func(_ *http.Request, via []*http.Request) error {
switch {
case n == NoFollow:
return http.ErrUseLastResponse
case n < len(via):
return fmt.Errorf("stopped after %d redirects", n)
default:
return nil
}
}
}
}
// Proxy returns a functional option which sets the `Proxy` field on
// the http.Client's Transport
func Proxy(proxy func(*http.Request) (*url.URL, error)) func(*Attacker) {
return func(a *Attacker) {
tr := a.client.Transport.(*http.Transport)
tr.Proxy = proxy
}
}
// Timeout returns a functional option which sets the maximum amount of time
// an Attacker will wait for a request to be responded to and completely read.View on GitHub (pinned to cf58112690)
Solutions
- Increase the limit with a higher MaxRedirects(n) to accommodate the target's chain length.
- Use MaxRedirects(-1) (NoFollow) to not follow redirects at all (returns the first non-redirect response instead of this error).
- Fix the server-side redirect loop (scheme, trailing slash, cookie/Host handling).
- Inspect recorded responses' Location headers to distinguish a loop from a deep chain.
Example fix
// before attacker.MaxRedirects(2) // after attacker.MaxRedirects(10) // or attacker.MaxRedirects(vegeta.NoFollow)
Defensive patterns
Strategy: try-catch
Try / catch
for res := range results {
if res.Code == 0 && res.Error != "" {
if strings.Contains(res.Error, "stopped after") {
// redirect limit hit: raise MaxRedirects or use NoFollow
continue
}
}
// handle other errors...
} Prevention
- Set MaxRedirects to a value above the target's known redirect chain length.
- Use MaxRedirects(NoFollow) if you want the first non-redirect response.
- Watch for redirect loops (same Location repeating) and fix server config.
- Treat this error string as a signal to inspect the Location chain, not a crash.
When it happens
Trigger: Hitting a target whose redirect chain is longer than the configured MaxRedirects(n), with n a positive number (not NoFollow/-1). E.g. MaxRedirects(5) against an endpoint redirecting 6+ times.
Common situations: Redirect loops caused by misconfigured TLS/hosts (http->https bouncing), cookie-less clients re-triggering redirects, load balancers redirecting repeatedly, or simply setting the limit too low.
Related errors
AI-assisted analysis of tsenart/vegeta@cf58112690 (2026-08-31).
Data as JSON: /api/errors/32c542f87e861384.
Report an issue: GitHub.