trailing-slash loop high
Trailing-Slash Redirect Loop
Two normalization rules disagree on the trailing slash, so /page and /page/ bounce back and forth forever.
What you see
This page isn't working example.com redirected you too many times. ERR_TOO_MANY_REDIRECTS
What’s actually happening
The browser shows ERR_TOO_MANY_REDIRECTS and never paints. curl -IL stops with 'Maximum (50) redirects followed' and the trace flips between 301 /page -> /page/ and 301 /page/ -> /page. Often only some routes loop while the homepage loads fine, which makes it look intermittent.
Common causes
- Framework and server disagree: Next.js trailingSlash:false strips the slash while an Nginx 'rewrite ^([^.]*[^/])$ $1/ permanent' adds it back.
- A CDN rule (Cloudflare Bulk Redirects, an edge 'always add trailing slash' Page Rule) fights the origin's canonical handling.
- WordPress canonical_redirect() appends a slash to a path that .htaccess or a plugin just removed.
- Static host quirk: S3 + CloudFront treats /dir and /dir/ as different keys and one rule normalizes the opposite way.
- A reverse proxy strips the slash before forwarding, then the app's router re-adds it on the response.
How to fix it
- Find both ends of the loopRun curl -sIL https://example.com/page and read the Location header on each hop. You'll see one layer sending to /page and another to /page/. Note which component emits each 301 (server header, Via, CF-Ray).
- Pick one canonical form and disable the other ruleDecide slash or no-slash, then turn off the competing rule. If Next.js owns it (trailingSlash in next.config.js), delete the Nginx rewrite/CDN Page Rule. Don't enforce the same policy in two places.
- Move enforcement to the outermost layer onlyLet the CDN or front proxy normalize once and have the origin accept whatever it receives. Configure the backend to serve both /page and /page/ with 200 instead of redirecting.
- Clear cached redirects before retesting301s are cached hard by browsers and CDNs. Purge the CDN path and test in a fresh private window (or curl with no cache) so you're not chasing a stale 301.
Stop it recurring
Enforce slash policy in exactly one layer and assert it with a curl redirect-trace check in CI.
Related errors