Laravelの419エラー(Page Expired)とは、CSRFトークンの検証失敗またはセッションの期限切れによってフォーム送信が拒否されるエラーです。原因はCSRFトークンの検証失敗かセッション期限切れのどちらかにほぼ絞られます。本ガイドでは、フォームやAjaxのトークン設定、セッション周りの設定など原因別に、今すぐコピペで試せる解決手順とコード例をステップ形式で紹介します。
なお、Laravel 419エラーの原因と解決策:セッション問題を解消する方法では、セッション問題を中心にさらに詳しく解説しています。
419エラーの原因
まず、419エラーの原因を理解することが重要です。このエラーは、CSRF(Cross-Site Request Forgery)トークンの検証に失敗した場合や、セッションが失効した場合に発生します。CSRFトークンは、Webアプリケーションのリクエストが正当なものであるかを検証するために使用されます。したがって、CSRFトークンが正しく送信されない場合、またはセッションが期限切れのときに、このエラーが発生します。
原因別チェックリスト
419 Page Expiredが発生したときは、以下の原因を順番に確認しましょう。
- CSRFトークンの不備: フォームに
@csrfディレクティブが含まれているか確認する - セッション期限切れ: セッションの有効期間が短すぎていないか確認する(
config/session.phpのlifetime) - Cookie設定の問題:
SESSION_SECURE_COOKIEやSESSION_SAME_SITEの設定が環境に合っているか確認する - APP_KEYの問題:
.envのAPP_KEYが正しく設定・暗号化されているか確認する(APP_KEYを変更するとセッションが無効になる) - フォーム放置によるタイムアウト: フォームを長時間放置するとセッションが切れるため、セッション時間を延ばすか自動更新を実装する
- SESSION_DOMAIN / Cookieの不整合: サブドメインをまたぐ運用や本番環境で
SESSION_DOMAINがドメインと一致しているか確認する - ブラウザの「戻る」ボタン(bfcache): フォーム送信後に「戻る」で古いページを再送信していないか確認する
- 複数サーバー・ロードバランサー環境:
SESSION_DRIVER=fileのままサーバー間でセッションが共有されていないケースがないか確認する
CSRFトークンの不備を確認する
フォーム内のCSRFトークンをチェック
Laravelのフォームを使う場合、CSRFフィールドを忘れずに追加する必要があります。これは、{{ csrf_field() }} またはShort-handの@csrfディレクティブを利用して行います。
<form method="POST" action="/example">
@csrf
<!-- Your form fields here -->
</form>
トークンの送信確認
フォームからのトークン送信が正しく行われているか、ブラウザの開発ツールを使用して確認します。ネットワークタブからフォーム送信時のリクエストを調べ、リクエストボディにトークンが含まれているか確認してください。
セッション設定を確認する
セッションタイムアウトの見直し
セッションタイムアウトが短すぎる場合、セッションが予想以上に早く切れることがあります。config/session.php ファイルでセッションのlifetime設定を確認し、必要に応じて延長してください。
'lifetime' => env('SESSION_LIFETIME', 120),
セッションドライバーの選択
セッションドライバーが適切でない場合も原因となることがあります。特に、ファイルベースのセッションストレージを使用している場合、多くのリクエストがあるとパフォーマンスへの影響も考えられます。可能であれば、より適したドライバー(例:redis、database)に切り替えてセッションを管理する方法も検討してください。
'driver' => env('SESSION_DRIVER', 'file'),
CSRFトークンの設定
CSRF Cookieの確認
Laravelでは、デフォルトでCSRFトークンがCookieとしてクライアントに送信されます。このCookieがないとリクエストが不正と見なされることがあります。VerifyCsrfTokenミドルウェアを確認し、必要な設定がされているかチェックしてください。
AJAXリクエストでのCSRFトークン
AJAXを使用してリクエストを送信する場合、リクエストヘッダーにCSRFトークンを含める必要があります。まず、HTMLの <head> にメタタグを追加します:
<meta name="csrf-token" content="{{ csrf_token() }}">
jQueryを使っている場合は次のようにグローバル設定できます:
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
Axiosを使っている場合(LaravelのデフォルトHTTPクライアント)は、自動的にCSRFトークンが付与されます。ただし、resources/js/bootstrap.js で以下が設定されているか確認してください:
import axios from 'axios';
window.axios = axios;
window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
Fetch APIを使う場合は、手動でトークンをヘッダーに付与する必要があります:
const token = document.querySelector('meta[name="csrf-token"]').getAttribute('content');
fetch('/your-endpoint', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRF-TOKEN': token,
},
body: JSON.stringify({ key: 'value' }),
});
AJAXリクエストで419が返ってくる場合、エラーハンドリングでユーザーに再読み込みを促すとUXが向上します:
axios.post('/your-endpoint', data).catch(error => {
if (error.response && error.response.status === 419) {
alert('セッションの有効期限が切れました。ページを再読み込みしてください。');
window.location.reload();
}
});
APP_KEYの不一致を確認する
.env の APP_KEY はセッションデータの暗号化に使われています。サーバー移行や環境コピー、デプロイ時の設定ミスなどでAPP_KEYが変わると、既存セッションが復号できなくなり419エラーになります。
php artisan key:generate
php artisan config:clear
.env を変更した直後は設定キャッシュが古いままのことがあるため、config:clear(本番ではconfig:cacheでの再キャッシュ)を必ず実行してください。key:generateの詳しい構文はphp artisan key:generateの使い方|APP_KEY生成コマンドの構文と注意点で解説しています。
SESSION_DOMAIN / Cookie設定を確認する
サブドメインをまたいで動作するアプリや本番環境では、SESSION_DOMAIN や SESSION_SECURE_COOKIE の設定がドメイン構成と一致していないとCookieが正しく送受信されず419エラーになります。
SESSION_DOMAIN=.example.com
SESSION_SECURE_COOKIE=true
ブラウザの「戻る」ボタン(bfcache)を確認する
フォームを送信した後に「戻る」ボタンでフォームページへ戻り、ブラウザのキャッシュ(bfcache)に残った古いページのまま再送信すると、CSRFトークンが既に無効になっており419エラーが発生します。Laravel側の不具合ではなくブラウザの仕様による挙動です。pageshowイベントでページ復元を検知してリロードすることで回避できます。
window.addEventListener('pageshow', function (event) {
if (event.persisted) {
window.location.reload();
}
});
複数サーバー・ロードバランサー環境を確認する
複数台のWebサーバーで運用している場合、SESSION_DRIVER=fileのままだとセッションが各サーバーのローカルディスクに保存され、リクエストのたびに別サーバーへ振り分けられるとセッションが見つからず419エラーになります。ロードバランサー配下ではredisやdatabaseなど、サーバー間で共有できるセッションドライバを使用してください。
# .env
SESSION_DRIVER=redis
HTTP中間層を確認する
ミドルウェア設定の確認
app/Http/Kernel.php内のミドルウェア設定を確認し、VerifyCsrfTokenミドルウェアが適切に登録されていることを確認します。
CSRFトークンの例外設定
一時的にCSRF検証を無効にすることも可能ですが、これは非常に慎重に行う必要があります。検証を無効にすることでセキュリティリスクが増えるため、本番環境では推奨されません。ただし、開発環境で原因を特定するために一時的に設定することは許される場合もあります。設定方法はLaravelのバージョンによって異なります。
Laravel 10以前: app/Http/Middleware/VerifyCsrfToken.phpの$exceptプロパティに除外したいルートを指定します。
protected $except = [
// 'excluded/routes/here',
];
Laravel 11以降: app/Http/Kernel.phpが廃止され、bootstrap/app.phpのwithMiddleware()内で設定します。
// bootstrap/app.php
->withMiddleware(function (Middleware $middleware) {
$middleware->validateCsrfTokens(except: [
'excluded/routes/here',
]);
})
デバッグとログの活用
エラーが続く場合、Laravelのログを確認することも非常に有益です。storage/logs/laravel.logにはエラーの詳細が記録されていることがあり、それが解決の手がかりになる場合があります。また、config/logging.phpでログレベルや出力先を変更して、より詳しい情報を取得することも考えられます。
よくある質問(FAQ)
Page Expiredとは?
「Page Expired」はHTTPステータスコード419のエラーメッセージです。Laravelではデフォルトでこのメッセージを表示し、CSRFトークンの検証失敗またはセッション期限切れが発生したことを示します。一般的なHTTPエラーとは異なり、LaravelがCSRF保護のために独自に定義したステータスコードです。
LaravelでPage Expiredが出る原因は?
主な原因は以下の通りです:
- フォームに
@csrfディレクティブが含まれていない - セッションが期限切れになっている(フォームを長時間放置した場合など)
- Cookie設定の不整合(HTTPS環境での
SESSION_SECURE_COOKIE設定など) - AJAXリクエストにCSRFトークンが含まれていない
- APP_KEYが変更または未設定でセッションが無効になった
より詳しい原因別の解説はLaravel 419エラーの原因と解決策をご覧ください。
ロードバランサー配下だけで419が頻発するのはなぜ?
SESSION_DRIVER=fileのまま複数サーバーで運用していると、リクエストのたびに振り分け先サーバーが変わり、セッションファイルが見つからず419になります。redisやdatabaseなどサーバー間で共有できるセッションドライバに変更してください。
再発を防ぐには?
再発を防ぐには、以下を実践しましょう:
- すべてのフォームに
@csrfを必ず含める - セッションの
lifetimeを適切な値に設定する(デフォルトは120分) - AJAXリクエストには常にCSRFトークンをヘッダーに付与する
- 本番環境では
APP_KEYを安易に変更しない - 419エラー発生時にユーザーへわかりやすいメッセージを表示する
結論
「419 Page Expired」エラーは、Laravelを使用する上でよく発生する問題ですが、正しい設定と理解があれば解決することは十分に可能です。CSRFトークンやセッションの管理に注意を払い、上記の解決策を試してみてください。それでも問題が解決しない場合は、Laravelの公式ドキュメントやコミュニティフォーラムで助けを求めるのも有効な手段です。問題の根本を見極め、一つずつ解決していくことで、より安全で信頼性の高いアプリケーションを構築できるでしょう。

コメント