Skip to content
Hosting Operations9 min read

419 Error Code: 8 Common Questions [Solved]

Fix 419 error code in Laravel and other frameworks with CSRF token solutions, session config checks, and cache clearing steps.

Written by Abdul AbrorTechnical Hosting Support Engineer
text
On this page

TL;DR — Key takeaways

  • 419 errors signal an expired or missing CSRF token, blocking form submissions and AJAX requests as a security measure
  • Laravel 419 expired errors fix by verifying the csrf_token() helper in forms and ensuring VerifyCsrfToken middleware is active
  • Session configuration problems cause token expiration—check SESSION_DRIVER, SESSION_LIFETIME, and file permissions in .env
  • Clearing route, config, and view caches resolves persistent 419 errors after deployment or configuration changes

You submit a form and hit a 419 error screen. No validation message, no redirect—just a blank error page or a generic Laravel exception.

The 419 status code means your CSRF token expired or never made it into the request. This happens with forgotten token fields, session storage problems, or cache mismatches after deployment. In support tickets I handled, the usual culprit was either a missing @csrf directive in Blade templates or a SESSION_DRIVER pointing to a directory the web server couldn't write to.

What Is a 419 Error Code?

HTTP 419 is an unofficial status code used by Laravel and a few other frameworks to signal that a request failed CSRF token validation. CSRF tokens are random strings tied to your session, embedded in forms and checked on the server. They prevent attackers from tricking your browser into submitting requests to your application.

When you load a page with a form, the framework generates a token and stores it in your session. The form includes a hidden field with that token. On submission, the server compares the token in the request to the one in the session. A mismatch or missing token returns 419.

Session expiration causes most 419 errors. If your session lifetime is short or your session storage fails, the token becomes invalid before you submit the form. Cached pages also serve stale tokens that no longer match the current session.

Why Does Laravel Return a 419 Expired Error?

Laravel includes CSRF protection by default through the VerifyCsrfToken middleware, applied to all routes in the web middleware group. Every POST, PUT, PATCH, or DELETE request must include a valid token in a _token field or an X-CSRF-TOKEN header.

The error triggers when the token in the request doesn't match the one stored in the session, or the session no longer exists. Common causes:

Session configuration points to a nonexistent or read-only directory. Check storage/framework/sessions exists and has write permissions (755 or 775 depending on your server setup). The web server user—www-data on Ubuntu/Debian, nginx on some systems—must own that directory or have write access.

The application cache holds stale config or route definitions. After changing SESSION_DRIVER or SESSION_LIFETIME in .env, run php artisan config:clear and php artisan route:clear. Otherwise Laravel reads cached values that don't reflect your changes.

Forms loaded before login persist across authentication. The session ID changes after login, invalidating any tokens generated beforehand. Redirect users to a fresh page after authentication instead of letting them submit a pre-login form.

How Do I Add CSRF Tokens to Forms in Laravel?

Blade templates use the @csrf directive inside <form> tags. This generates a hidden input field with the token:

<form method="POST" action="/submit"> @csrf <input type="text" name="username"> <button type="submit">Submit</button> </form>

Plain PHP uses the csrf_field() helper, which returns the same hidden input HTML. For AJAX requests, include the token in a meta tag in your layout:

<meta name="csrf-token" content="{{ csrf_token() }}">

Then set the X-CSRF-TOKEN header in your JavaScript. With Axios:

axios.defaults.headers.common['X-CSRF-TOKEN'] = document.querySelector('meta[name="csrf-token"]').getAttribute('content');

With fetch:

fetch('/api/endpoint', { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').content }, body: JSON.stringify({key: 'value'}) });

Check your browser's network inspector to confirm the token appears in the request payload or headers. A missing token always returns 419.

What Session Settings Cause 419 Errors?

SESSION_DRIVER controls where Laravel stores session data. Valid options include file, cookie, database, memcached, redis, dynamodb, and array. The file driver writes to storage/framework/sessions by default. If that directory doesn't exist or lacks write permissions, sessions fail silently and every request gets a new session ID, invalidating tokens immediately.

SESSION_LIFETIME sets the number of minutes a session remains valid. The default is 120 (two hours). If users spend more than that time on a page before submitting a form, the token expires. Increase the lifetime in .env if your forms take a long time to complete, but balance security against convenience.

SESSION_DOMAIN must match the domain serving your application. If you set SESSION_DOMAIN=example.com but access the site via www.example.com, the browser won't send the session cookie and Laravel treats every request as a new session. Leave this blank for single-domain applications or set it to .example.com (with a leading dot) to share sessions across subdomains.

SESSION_SECURE_COOKIE should be true in production if your site uses HTTPS. A secure cookie won't transmit over HTTP, so local development on http://localhost requires this set to false in your .env.local or .env.development file.

After changing any session setting, restart your queue workers if you use them and clear cached config with php artisan config:clear. Then test by opening a browser incognito window to avoid stale cookies.

How Do I Exclude Routes from CSRF Protection?

Some routes legitimately bypass CSRF checks: webhook endpoints receiving POST requests from third-party services, or API routes using token authentication instead of session cookies. Add these routes to the $except array in app/Http/Middleware/VerifyCsrfToken.php:

protected $except = [ 'webhook/stripe', 'api/external/*', ];

Use wildcards for route groups. Never add user-facing form routes here. An excluded route accepts requests from any origin, exposing your application to CSRF attacks.

API routes in routes/api.php use the api middleware group by default, which excludes CSRF protection in favor of token-based auth. You don't need to add these to $except unless you moved them to routes/web.php.

What If 419 Errors Persist After Fixing Tokens?

Check your reverse proxy or load balancer. If it terminates SSL, your application might see requests as HTTP even though users connect via HTTPS. Laravel generates secure cookies that the browser won't send back over the internal HTTP connection. Set TRUSTED_PROXIES in config/trusts.php or add the proxy IP to the $proxies array in app/Http/Middleware/TrustProxies.php.

Inspect session cookies in your browser's developer tools (Application tab in Chrome, Storage in Firefox). Confirm the session cookie exists and has the correct Domain, Path, and SameSite attributes. A SameSite=Strict cookie won't send on form submissions from external links; change SESSION_SAME_SITE to lax or none (with SESSION_SECURE_COOKIE=true) in .env if needed.

Test session persistence by adding this to a controller:

session()->put('test', 'value'); dd(session()->getId(), session()->get('test'));

Refresh the page. The session ID should stay the same and 'test' should return 'value'. If the ID changes on every request, your session storage is broken.

Review storage/logs/laravel.log for session write failures or permission errors. File driver issues usually log "Unable to create session file" or similar messages.

How Do I Clear Laravel Caches to Fix 419 Errors?

Run these four commands after deployment or .env changes:

php artisan config:clear php artisan route:clear php artisan view:clear php artisan cache:clear

Or use the combined command:

php artisan optimize:clear

This removes cached config, compiled routes, Blade view templates, and application cache. Restart php-fpm or your web server after clearing caches on some systems where opcache holds stale bytecode.

For persistent problems, delete everything in bootstrap/cache/ except .gitignore, then run php artisan optimize. This rebuilds all cached files from scratch.

Never run php artisan config:cache or php artisan route:cache in development. Cached config ignores .env changes until you clear the cache again, making debugging harder. Reserve caching for production where you control deployments.

How Do I Test and Prevent 419 Errors?

Add automated tests that submit forms and verify successful responses. A feature test in Laravel looks like this:

public function test_form_submission_succeeds() { $response = $this->post('/submit', [ 'username' => 'testuser', 'email' => '[email protected]', ]); $response->assertStatus(302); }

The test automatically includes a valid CSRF token. If your form processing code removes or disables CSRF protection accidentally, the test still passes but real users hit 419 errors. Add a test that explicitly checks for the token in the rendered form HTML to catch missing @csrf directives.

Monitor your logs for 419 responses. A spike indicates a session storage failure, a deployment that changed APP_KEY, or a recently added form missing token fields. Set up log alerts for HTTP 419 responses so you catch these before users report them.

Document your SESSION_DRIVER and SESSION_LIFETIME settings in your deployment runbook. When you change session storage from file to redis or memcached, clear all existing sessions to prevent confusion. The old file-based sessions won't exist in the new redis store, causing 419 errors for any users with cookies pointing to the old session IDs.

Quick troubleshooting checklist

  • Verify CSRF token is present in all POST, PUT, PATCH, DELETE forms using @csrf or csrf_field()
  • Check .env for SESSION_DRIVER, SESSION_LIFETIME, and SESSION_DOMAIN settings
  • Confirm storage/framework/sessions directory exists with correct write permissions (775 or 755)
  • Clear application cache: php artisan cache:clear && php artisan config:clear && php artisan route:clear
  • Inspect browser console for AJAX requests missing X-CSRF-TOKEN header
  • Add routes to VerifyCsrfToken $except array only if legitimately exempt (webhooks, API callbacks)
  • Test session persistence by printing session()->getId() before and after form submission
  • Review web server logs for session cookie delivery failures or SameSite attribute conflicts

FAQ

What causes a 419 error code?

A 419 error occurs when a web application rejects a request due to an expired or missing CSRF (Cross-Site Request Forgery) token. The token validates that the request originates from your application's own forms, not an external malicious site. Session expiration, misconfigured session storage, or forgotten token fields in forms trigger this error.

How do I fix 419 error code in Laravel?

Add @csrf inside every form that posts data, verify the VerifyCsrfToken middleware is registered in app/Http/Kernel.php under the web middleware group, and check that your SESSION_DRIVER in .env is correctly configured (file, redis, or database). Clear cached config with php artisan config:clear after changes. For AJAX requests, include the X-CSRF-TOKEN header with the token from the meta tag.

Why does Laravel show 419 expired after deployment?

Deployment often changes the APP_KEY or clears session storage, invalidating existing tokens. Run php artisan key:generate only once and commit the key to your .env (or inject it via environment variables). After deployment, clear all caches with php artisan optimize:clear and verify the storage/framework/sessions directory has write permissions for the web server user (www-data or nginx).