The error message:
All Inertia requests must receive a valid Inertia response, however a plain JSON response was received.
means that Inertia is expecting a special response header (X-Inertia) and/or a specific response structure, but is instead receiving a plain JSON response. This usually happens when:
- The request is not being routed through Laravel correctly (e.g., static file, wrong entrypoint, or misconfigured web server).
- The request is not hitting the Inertia controller as expected.
- There is a proxy or web server misconfiguration.
Given your setup, here are the most likely causes and solutions:
1. Nginx Configuration
Problem:
If your Nginx is not configured to route all requests to public/index.php, then Inertia requests (especially those with Accept: application/json or X-Inertia headers) may not reach Laravel, and instead, Nginx may serve a static file or a default error response.
Solution:
Ensure your Nginx config includes the following (inside your server block):
location / {
try_files $uri $uri/ /index.php?$query_string;
}
This ensures all requests (except for existing files) are routed to Laravel.
2. Trusted Proxies
Problem:
When running behind Caddy (reverse proxy) and Docker, Laravel may not correctly identify the original request headers (like X-Requested-With, X-Inertia, etc.) due to missing trusted proxy configuration.
Solution:
Set up trusted proxies in your App\Http\Middleware\TrustProxies:
protected $proxies = '*'; // or ['127.0.0.1', '::1'] for local docker
And ensure you have the correct headers:
protected $headers = Request::HEADER_X_FORWARDED_ALL;
3. .env Configuration
Problem:
If APP_URL or SESSION_DOMAIN is not set correctly, Inertia requests may not be handled as expected.
Solution:
Check your .env:
APP_URL=https://demo-inertia.company.example
SESSION_DOMAIN=.company.example
4. Caddy Reverse Proxy
Problem:
Caddy may not be forwarding all headers, especially custom ones like X-Inertia.
Solution:
Caddy generally forwards all headers, but if you have custom header manipulation, ensure nothing is stripped.
5. Volumes and File Permissions
Problem:
Your Docker volumes for storage may be causing permission issues or not mounting as expected, leading to unexpected errors.
Solution:
Double-check your volume mounts and permissions, especially for storage and logs.
6. Debugging
Steps:
- Check Nginx logs (
logs/nginx) and Laravel logs (logs/application) for errors. - Inspect network requests in your browser dev tools. Check the response for Inertia requests—are they hitting Laravel? What is the response?
- Add a test route in Laravel that returns an Inertia response and hit it directly.
Summary Checklist
- Nginx config uses
try_files $uri $uri/ /index.php?$query_string; - Laravel trusted proxies are set (
TrustProxiesmiddleware) -
.envhas correctAPP_URLandSESSION_DOMAIN - Caddy is not stripping headers
- Docker volumes and permissions are correct
Example Nginx Config
Here’s a minimal example for your Nginx container:
server {
listen 80;
server_name _;
root /var/www/public;
index index.php index.html;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
fastcgi_pass app:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
include fastcgi_params;
}
location ~ /\.ht {
deny all;
}
}
If you update your Nginx config as above and ensure trusted proxies are set, your Inertia requests should work as expected inside Docker.