Common causes
- SCRIPT_FILENAME is not set, or not set to $document_root$fastcgi_script_name
- root is defined inside another location block, so the PHP location has the wrong root
- The file does not exist at that path, or the request has a typo
- PHP-FPM runs in a container or chroot where the path is different
- The PHP-FPM pool user cannot read the file or traverse its parent folders
- open_basedir or security.limit_extensions blocks the path or extension
How to fix it
- Set SCRIPT_FILENAME correctly. Inside the PHP location add fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;. On Debian/Ubuntu, include snippets/fastcgi-php.conf and fastcgi_params already handle this.
- Move root to the server block. Define root /home/user/public_html; at the server level, not only inside location /. Then every location, including the PHP one, uses the same root.
- Confirm the file exists. Run ls -l /home/user/public_html/index.php using the exact path from the error. Fix the path or deploy the missing file.
- Check read permissions. Run sudo -u www-data stat /home/user/public_html/index.php (use your pool user). Each parent directory needs execute (x) permission for that user.
- Match container paths. If PHP-FPM runs in Docker, mount the code at the same path in both the Nginx and PHP containers, or set SCRIPT_FILENAME to the PHP container's path.
- Reload and test. Run sudo nginx -t and sudo systemctl reload nginx, then request the page again and watch the error log.
Server block with root at server level
server {
server_name example.com;
root /home/user/public_html;
index index.php;
location / {
try_files $uri $uri/ /index.php?$args;
}
location ~ \.php$ {
try_files $uri =404;
fastcgi_pass unix:/run/php/php8.3-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
} How to stop it happening again
- Keep root in the server block
- Use try_files $uri =404 in the PHP location so missing files 404 in Nginx
- Use identical code paths across Nginx and PHP containers
- Run nginx -t and load a PHP page after every config change