Primary script unknown is what PHP-FPM reports when nginx (or another web server) asks it to run a PHP file and that file path does not exist, or cannot be read, from PHP-FPM's point of view. The browser usually shows a plain "File not found." page with HTTP status 404, and the nginx error log has:
FastCGI sent in stderr: "Primary script unknown" while reading response header from upstream, client: 203.0.113.9, server: example.com, request: "GET /index.php HTTP/1.1", upstream: "fastcgi://unix:/run/php/php8.2-fpm.sock:", host: "example.com"
The web server and PHP-FPM are separate processes. nginx tells PHP-FPM which file to execute through the SCRIPT_FILENAME parameter. If that path is wrong, PHP-FPM answers "Primary script unknown." So the question is always: what path did nginx send, and does that path exist and is it readable by the PHP-FPM user?
Step 1: see the path nginx sends
Look at your fastcgi_param SCRIPT_FILENAME line (often inside include snippets/fastcgi-php.conf; or include fastcgi_params;). Then inspect the effective configuration:
sudo nginx -T 2>/dev/null | grep -nE "server_name|root |SCRIPT_FILENAME|fastcgi_pass|include .*fastcgi"
A common correct pattern:
server {
server_name example.com;
root /var/www/example.com/public;
index index.php;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php8.2-fpm.sock;
}
}
Distribution layouts differ: Debian and Ubuntu ship snippets/fastcgi-php.conf, while RHEL-style systems use include fastcgi_params; plus an explicit fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; line. Check the path and PHP-FPM socket name for your version.
Step 2: common causes
rootis missing or wrong inside thelocation ~ \.php$block. Ifrootis set only in another location,$document_rootcan be empty or a default folder. Putrootat theserverlevel.SCRIPT_FILENAMEuses a literal wrong prefix, such as/scripts$fastcgi_script_namecopied from an old tutorial.- The file really does not exist. The request for
/index.phphas no file at$document_root/index.php. Confirm withls -l /var/www/example.com/public/index.php. - Permissions. PHP-FPM's user (usually
www-data,nginxor a per-site user) cannot read the file or traverse parent directories. Test withsudo -u www-data test -r /var/www/example.com/public/index.php && echo ok. See PHP failed to open stream: Permission denied and nginx permission denied (13). - chroot or containers with different paths. If PHP-FPM runs in a chroot, a container, or a different mount namespace, the path nginx sends (
/var/www/...) may not exist there. Mount the same code at the same path in both containers, or setSCRIPT_FILENAMEto the path as PHP sees it. In Docker setups, nginx and PHP containers need the same volume mapped to the same path or an adjustedfastcgi_param. try_filesorrewriterules sending nonexistent scripts, such as/index.phpin a subdirectory when the app lives elsewhere, or a front controller that does not exist.security.limit_extensionsin the PHP-FPM pool restricts which extensions may run. Default is.php; a request for.php5or.phtmlfails if not allowed. Checkpool.d/www.conf.- Wrong virtual host. A request is matched by the wrong
serverblock and uses another site's root.nginx -Tshows which blocks claim a name. - Symlinks and deploy directories. Atomic deploys that swap a
currentsymlink can briefly produce missing paths, or$realpath_rootis needed so opcache sees the real path. Usefastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;andfastcgi_param DOCUMENT_ROOT $realpath_root;for such deployments. - SELinux denying PHP-FPM access; see the SELinux steps in the permission denied page above.
Step 3: test PHP-FPM directly
Make sure PHP-FPM itself is healthy and which socket it listens on:
sudo systemctl status php8.2-fpm
sudo ss -xlp | grep php
sudo grep -E "^(listen|user|group)" /etc/php/8.2/fpm/pool.d/www.conf
If nginx fastcgi_pass points to a socket that does not exist, you will get a connection error (502), not this message; see fix 502 Bad Gateway और nginx connect() failed (111). "Primary script unknown" means the connection succeeded, so the socket is correct and the path is wrong.
Create a test file to isolate the problem:
echo '<?php echo "ok ", __FILE__;' | sudo tee /var/www/example.com/public/t.php
curl -i https://example.com/t.php
If t.php works but /index.php does not, the application files are missing or unreadable. Delete the test file afterwards.
Apply and verify
sudo nginx -t && sudo systemctl reload nginx
Check the response with the HTTP स्टेटस चेकर; you want 200, not 404. Confirm headers with the HTTP Header Checker and keep an अपटाइम मॉनिटर on the home page so a bad deploy is flagged quickly.
अगले कदम
- Compare with nginx upstream timed out.
- Read Apache vs nginx troubleshooting.
- Tune workers: PHP-FPM server reached pm.max_children.
- Follow fix 500 internal server error.
सामान्य प्रश्न
Why does the browser show only File not found?
PHP-FPM sends that text itself when the script path fails. The detail is in the nginx error log.
Does this mean PHP-FPM is down?
No. PHP-FPM answered. It is rejecting the file path nginx gave it.
I use Docker. What is the usual cause?
The nginx container and the PHP container do not share the same code path. Mount the same volume at the same location in both.
Is the problem in PHP or nginx?
Almost always the nginx configuration or filesystem layout, not PHP code.
Get notified when this fix updates
Plus occasional practical tips on uptime and monitoring, nothing else. Unsubscribe anytime.
यह पेज सामान्य जानकारी है, जिसे हमारी संपादकीय टीम ने लिखा है और दस्तावेज़ीकरण बदलने पर अपडेट किया जाता है। सर्वर और प्रदाता अलग-अलग होते हैं, इसलिए बदलाव पहले सुरक्षित तरीके से जाँचें। देखें: संपादकीय नीति और अस्वीकरण.