Ffile2fix
Sign in Get started

How to fix Nginx "Primary script unknown"

FastCGI sent in stderr: "Primary script unknown" while reading response header from upstream, client: 203.0.113.5, server: example.com, request: "GET /index.php HTTP/1.1", upstream: "fastcgi://unix:/run/php/php8.3-fpm.sock:", host: "example.com"

PHP-FPM received a request but could not find or open the PHP file at the path Nginx sent in SCRIPT_FILENAME. Visitors usually see a plain 'File not found.' page. The most common cause is a missing or wrong SCRIPT_FILENAME, or a root that does not match where the files are.

Also appears as: File not found. · FastCGI sent in stderr: "Unable to open primary script: /var/www/html/index.php (No such file or directory)" · FastCGI sent in stderr: "Access to the script '/home/user/public_html/index.php' has been denied (see security.limit_extensions)" · 404 Not Found on every .php page while static files load

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

  1. 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.
  2. 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.
  3. 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.
  4. 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.
  5. 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.
  6. 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

Frequently asked questions

Why do I see 'File not found.' instead of a normal 404?

That plain text comes from PHP-FPM, not Nginx. It means the request reached PHP-FPM with a path it could not open.

Why does try_files $uri =404 help?

Nginx checks that the PHP file exists before sending it to PHP-FPM. Missing files return a normal 404, and it also blocks some path tricks.

Static files work but PHP does not. Why?

Static files use the root in location /, while the PHP location may have a different or missing root. Put root at the server level.