Primary script unknown high
PHP-FPM "Primary script unknown" (File not found)
nginx handed PHP-FPM a SCRIPT_FILENAME path that PHP-FPM cannot find or read, so it returns a blank File not found.
What you see
# browser: File not found. # php-fpm error log: FastCGI sent in stderr: "Primary script unknown" while reading response header from upstream
What’s actually happening
Every PHP page shows a bare 'File not found.' while static files (images, CSS) serve fine, which points at the FastCGI handoff rather than nginx itself. PHP-FPM logs 'Primary script unknown' because the SCRIPT_FILENAME nginx sent does not resolve to a file the FPM worker can open. The path is either wrong or the FPM user lacks permission to read it. Nothing in the PHP application runs, because PHP never finds the script to execute.
Common causes
- root is set inside the location ~ \.php$ block (or missing) so the computed path is wrong; root belongs in the server block.
- fastcgi_param SCRIPT_FILENAME is built incorrectly, for example using $document_root$fastcgi_script_name when $realpath_root or the right include is needed.
- The PHP-FPM pool runs as a different user (www-data) than owns the files, and directory permissions block traversal into the docroot.
- nginx and PHP-FPM run in different filesystem namespaces (separate containers, or chroot/open_basedir), so the path nginx sees does not exist for FPM.
- A wrong or duplicated try_files / SCRIPT_FILENAME from copy-pasted config sends a path that points outside the actual web root.
How to fix it
- Print the path PHP-FPM is actually receivingTemporarily set fastcgi_param SCRIPT_FILENAME and add a return or log, or check the FPM access log with %f. Knowing the exact path FPM tried to open tells you immediately whether it is a wrong root or a permission problem.
- Fix the root and SCRIPT_FILENAMEPut root /var/www/example/public; in the server block, not the php location. Set fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; (or include the standard fastcgi.conf, which sets it). Confirm the path it builds is a real file on disk.
- Check ownership and traversal permissionsVerify the PHP-FPM pool user (grep user in the pool .conf) can read the file: namei -l /var/www/example/public/index.php. Every parent directory needs execute (x) for traversal, not just the file.
- Reconcile paths across containersIf nginx and php-fpm run in separate containers, the docroot must be mounted at the identical path in both, since SCRIPT_FILENAME is literal. A path that exists only in the nginx container will always be 'unknown' to FPM.
- Reload and retestAfter fixing config, nginx -t && systemctl reload nginx, and restart php-fpm if you touched the pool. Load a known .php file and confirm it executes instead of returning File not found.
Stop it recurring
Keep root in the server block and use the distro's stock fastcgi_param/fastcgi.conf snippet so SCRIPT_FILENAME is built correctly, then confirm the FPM user can read the docroot.
Related errors