How to Fix “Primary Script Unknown” Error in Nginx + PHP-FPM Setup


2 views

When configuring Nginx with PHP-FPM, one of the most frustrating errors you might encounter is:

FastCGI sent in stderr: "Primary script unknown" while reading response header from upstream

This typically manifests as a "File not found" error in the browser, even when the file clearly exists on your server.

The error occurs when Nginx can't properly communicate the script location to PHP-FPM. Common scenarios include:

  • Incorrect root directive in Nginx configuration
  • Mismatched permissions between Nginx and PHP-FPM users
  • Improper fastcgi_param SCRIPT_FILENAME setting
  • Path translation issues between Nginx and PHP-FPM

Here's a properly configured Nginx server block for PHP processing:

server {
    listen 80;
    server_name example.com;
    root /var/www/example.com/public;
    index index.php index.html;

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

    location ~ \.php$ {
        include fastcgi_params;
        fastcgi_pass unix:/var/run/php/php5.6-fpm.sock;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param PATH_INFO $fastcgi_script_name;
        fastcgi_intercept_errors on;
    }
}

1. Verify file existence and permissions:

ls -la /var/www/example.com/public/index.php

2. Check Nginx and PHP-FPM user alignment:

ps aux | grep nginx
ps aux | grep php-fpm

3. Test PHP-FPM connectivity:

SCRIPT_NAME=/test.php \
SCRIPT_FILENAME=/var/www/test.php \
QUERY_STRING= \
REQUEST_METHOD=GET \
cgi-fcgi -bind -connect /var/run/php/php5.6-fpm.sock

Case 1: The root directive is set in server block but missing in location block.

Fix: Either move root to http context or duplicate it in location blocks.

Case 2: Using $request_filename instead of $document_root$fastcgi_script_name.

Fix: Stick to the standard pattern shown in the configuration above.

Case 3: PHP-FPM pool configuration has different chroot or chdir settings.

Fix: Check /etc/php/5.6/fpm/pool.d/www.conf for conflicting directives.

For stubborn cases, enable detailed logging:

# In nginx.conf
error_log /var/log/nginx/error.log debug;

# In PHP-FPM pool config
catch_workers_output = yes
php_admin_value[error_log] = /var/log/fpm-php.www.log
php_admin_flag[log_errors] = on

Then monitor both logs while reproducing the issue:

tail -f /var/log/nginx/error.log /var/log/fpm-php.www.log

While fixing this issue, be mindful of:

  • Never set permissions to 777 - use proper user/group ownership
  • Avoid using alias with PHP locations
  • Keep PHP-FPM pools isolated for different applications
  • Regularly audit your fastcgi_param directives

When you see the error "Primary script unknown" in your Nginx error logs while using PHP-FPM, it typically indicates a path resolution problem between Nginx and PHP-FPM. The web server cannot locate the PHP script you're trying to execute.

Here's a typical problematic Nginx configuration that could cause this:


location ~ \.php$ {
    fastcgi_pass unix:/var/run/php5-fpm.sock;
    fastcgi_index index.php;
    include fastcgi_params;
}

The crucial missing piece here is the SCRIPT_FILENAME parameter. Without it, PHP-FPM doesn't know which file to execute.

Here's the corrected version that should resolve the issue:


location ~ \.php$ {
    try_files $uri =404;
    fastcgi_split_path_info ^(.+\.php)(/.+)$;
    fastcgi_pass unix:/var/run/php5-fpm.sock;
    fastcgi_index index.php;
    include fastcgi_params;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}

Even with correct configuration, permission issues can cause the same error. Ensure:

  • Nginx worker process has read permissions for PHP files
  • PHP-FPM pool runs under a user with execute permissions
  • Directory tree has proper traversal permissions (typically 755)

If your Nginx and PHP-FPM use different document roots, you'll need to explicitly set the path:


fastcgi_param SCRIPT_FILENAME /path/to/your/webroot$fastcgi_script_name;

To troubleshoot further:

  1. Check PHP-FPM logs: /var/log/php5-fpm.log
  2. Verify file existence: php -r "var_dump(file_exists('/path/to/script.php'));"
  3. Test FastCGI connectivity: SCRIPT_FILENAME=/path/to/script.php REQUEST_METHOD=GET cgi-fcgi -bind -connect /var/run/php5-fpm.sock