Knowledge

nginx rewrite or internal redirection cycle

#Nginx

This error means nginx kept redirecting a request back to itself until it gave up. Almost always a try_files directive that loops, producing a 500 error.

Published by Mark van Eijk on June 23, 2026 · 1 minute read

  1. About the error
  2. Why do I see this error
  3. Solution
  4. Use the standard Laravel/PHP try_files
  5. Check the root actually contains index.php

About the error

The page returns a 500 and the nginx error log shows:

rewrite or internal redirection cycle while internally redirecting to "/index.php"

nginx tried to resolve a request, that resolution pointed at another location, which pointed back, and so on. After 10 internal redirects nginx assumes a loop and aborts with a 500.

Why do I see this error

The classic cause is a try_files that, when nothing matches, falls back to a target that itself triggers the same try_files again. For a PHP app it usually means:

  • The fallback file (index.php) doesn't exist at the expected path, so the fallback re-enters the same block.
  • The root is wrong, so nginx never finds the real file and keeps redirecting.
  • A try_files pointing at a named location or URI that loops back.

Solution

Use the standard Laravel/PHP try_files

A correct front-controller setup looks like this. Note the $uri and $uri/ are tried first, and the final fallback passes the path as a query string rather than re-requesting a file:

server {
    root /var/www/html/public;
    index index.php;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location ~ \.php$ {
        include fastcgi_params;
        fastcgi_pass unix:/run/php/php8.3-fpm.sock;
        fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
    }
}

Check the root actually contains index.php

The most common real cause is a wrong root. If /var/www/html/public/index.php doesn't exist, the fallback can never resolve and loops:

ls -l /var/www/html/public/index.php

Point root at the directory that genuinely contains the front controller (for Laravel that's public, not the project root).

Validate and reload after fixing:

nginx -t && systemctl reload nginx

For a deeper look at how try_files resolves requests, see the nginx try_files article. A redirect loop that happens in the browser rather than inside nginx shows up as ERR_TOO_MANY_REDIRECTS instead.

Subscribe to our newsletter

Do you want to receive regular updates with fresh and exclusive content to learn more about web development, hosting, security and performance? Subscribe now!

Related articles

Server Side Includes (SSI) in nginx

This error means nginx kept redirecting a request back to itself until it gave up. Almost always a try_files directive that loops, producing a 500 error.

Read more →

Configure Content Security Policy with nonce using nginx

This error means nginx kept redirecting a request back to itself until it gave up. Almost always a try_files directive that loops, producing a 500 error.

Read more →