Skip to content
Troubleshooting⏱️ 10 min read·

Laravel “419 Page Expired”: CSRF Token Mismatch Causes and Fixes

Diagnose and fix the infamous 419 Page Expired error in Laravel. Covers missing @csrf directives, session driver permissions, AJAX headers, and excluding payment gateway webhooks.

MN
Manoj NeupaneSoftware Developer & Programming Instructor
#Laravel#CSRF#419 Page Expired#PHP#Session#Debugging
🎯 Who This Tutorial Is For

📋 Prerequisites
  • ✓A Laravel application (Laravel 10, 11, or 12)
  • ✓Access to Blade templates and configuration files

🚀 What You Will Learn & Build

  • ▸The security purpose of CSRF tokens in web applications
  • ▸The 4 common causes of the 419 HTTP status code in Laravel
  • ▸How to fix AJAX requests and payment gateway callbacks
1

What Does '419 Page Expired' Actually Mean?

HTTP status code 419 is a custom status code utilized by Laravel to signify **CSRF Token Mismatch**. Every non-GET request (POST, PUT, DELETE) in Laravel must include a valid CSRF token that matches the token stored in the user's active session. If the token is missing, expired, or invalid, Laravel aborts execution with a 419 error.
2

The 4 Solutions to Fix 419

### 1. Missing @csrf in Blade Forms Every HTML `
` in Blade must have the `@csrf` directive: ```html @csrf
``` ### 2. Excluding Payment Gateways / Webhooks External services like eSewa or Khalti cannot generate a Laravel session CSRF token. In Laravel 11/12, exclude them in `bootstrap/app.php`: ```php ->withMiddleware(function (Middleware $middleware) { $middleware->validateCsrfTokens(except: [ 'payment/callback/*', 'api/webhook/*' ]); }) ``` ### 3. AJAX / Axios Headers in Single Page Applications If sending requests via JavaScript, include the token in your HTML ``: ```html ``` And configure Axios globally: ```javascript axios.defaults.headers.common['X-CSRF-TOKEN'] = document.querySelector('meta[name="csrf-token"]').getAttribute('content'); ``` ### 4. Storage Folder Permissions on Shared Hosting If Laravel cannot write sessions to `storage/framework/sessions`, sessions are lost immediately on the next request. Run on your server: ```bash chmod -R 775 storage bootstrap/cache ```

✨ Expected Output & Verification

Flawless form submissions without session drops or 419 expiration screens.

🧪 How to Test the Implementation

  1. 1Submit your form and inspect form payload in browser Network tab
  2. 2Confirm '_token' is present in request body
  3. 3Clear application cache with 'php artisan optimize:clear'

⚠️ Common Errors & How to Fix Them

❌Session expires immediately after login on shared hosting

Root Cause: SESSION_DOMAIN in .env does not match your exact domain, or storage folder is read-only.

Fix: Leave SESSION_DOMAIN=null or set it to .yourdomain.com.np.

🛡️ Security Considerations & Best Practices

  • !Never disable CSRF protection globally on web routes. Only exclude verified third-party webhook endpoints.

❓ Frequently Asked Questions (FAQ)

By default, Laravel session lifetime is 120 minutes. If the user sits idle, the session expires. Increase SESSION_LIFETIME in .env if longer sessions are required.

📌 Summary of Key Takeaways

Laravel 419 errors are resolved by adding @csrf to Blade forms, configuring Axios headers, exempting payment webhooks in bootstrap/app.php, and ensuring storage write permissions.

Official References & Further Reading