Submitting my form gives "419 | Page Expired". It happens randomly, more often after the page sits open for a while, and always on my production site behind Cloudflare. Laravel 12.
DEV3 Developer Forum
What causes '419 Page Expired' in Laravel and how do I fix it?
Every post is reviewed first. Usually reviewed within 24 hours.
1 reply
419 means the CSRF token check failed (TokenMismatchException). The token is tied to the session, so anything that breaks or expires the session breaks the form.
Checklist
- Missing token. Every non-GET form needs
@csrf. For AJAX send theX-CSRF-TOKENheader (from<meta name="csrf-token" content="{{ csrf_token() }}">) or rely on theXSRF-TOKENcookie with Axios. - Session expired.
SESSION_LIFETIMEdefaults to 120 minutes. A page left open overnight has a dead token. Increase the lifetime or refresh the token with a small keep-alive request. - Session not persisted. Check the session driver works:
storage/framework/sessionsmust be writable (file driver), or thesessionstable exists (database driver). After deploys with multiple servers, use a shared driver (database or Redis) instead of file. - Cookie issues in production. If you are on HTTPS and
SESSION_SECURE_COOKIE=true, but the app sees HTTP behind a proxy, the cookie is never set. Trust the proxy inbootstrap/app.php:
->withMiddleware(function (Middleware $middleware) {
$middleware->trustProxies(at: '*');
})
Also verify SESSION_DOMAIN matches the real domain and APP_URL is correct.
5. CDN caching. If Cloudflare or any page cache stores a page containing a token, every visitor gets someone else's stale token. Do not cache HTML for pages with forms (or logged in routes) and bypass the cache for them.
6. Third-party callbacks. Webhooks and payment gateway callbacks cannot send a token. Exclude their routes:
$middleware->validateCsrfTokens(except: ['stripe/webhook']);
Verify the webhook signature instead.
Debug tip: compare session()->token() before and after the failing request. If it changes each time, the session is not being saved.