【Laravel】本番だけ500エラーになった原因と解決(Cache+権限問題)

この記事について

環境Laravel + Apache(RHEL系)、本番/ステージング構成
目的ステージングでは正常なのに本番だけ500エラーになる原因を特定して復旧する
結果古い構造のキャッシュが本番にだけ残っていたのが原因。キャッシュキー変更で即効復旧し、cache:clear を阻んでいた権限問題を修正して本質解決

つまずきポイント要約

  • 本番だけキャッシュTTLを12時間にしていたため、古い構造のデータが本番にだけ残った
  • Bladeの ?? '' は500を止める応急処置にはなるが根本解決ではない
  • キャッシュキーにバージョン(v2:)を付けると、古いキャッシュを即座に無視できる
  • php artisan cache:clear が権限エラーで失敗するときは storage / bootstrap/cache のグループ・setgid・ACLを見直す

事象

ステージングでは正常に表示されるが、本番環境だけ500エラーになる

ログを見ると:

production.ERROR: Undefined array key "code"
production.ERROR: Undefined array key "word_url"
production.ERROR: Undefined array key "favorite_prefix"

Bladeで $tile['code'] などが存在しないと怒られている

原因

キャッシュの中身が古いままで、本番環境だけ更新されなかった。

$ttl = app()->isProduction() ? now()->addHours(12) : now()->addSeconds(1);

本番のみ12時間キャッシュが古いまま残る設定にしていた。

問題の箇所:

$table1Sections = Cache::remember("word_table1_sections:{$languageColumn}:{$wordUrlNo}", $ttl, function () {
    // buildWordTiles() の結果をキャッシュ
});

ここでキャッシュされる $tile が古い構造のデータだった。中に入るべき変数が不足してエラーが起こった。

対処

① 応急処置

Bladeでエラー回避:

:code="$tile['code'] ?? ''"
:word-url="$tile['word_url'] ?? ''"
:favorite-prefix="$tile['favorite_prefix'] ?? ''"

500エラーは止まるが、根本解決ではない

② キャッシュキーを変更(即効復旧)

Cache::remember("v2:word_table1_sections:...", ...)

古いキャッシュを無視できる

③ 権限の修正(本質対応)

キャッシュを削除すればいいだけのことだ、今回キャッシュが削除できずに苦労した。

$ php artisan cache:clear
   ERROR  Failed to clear cache. Make sure you have the appropriate permissions.

グループにapache追加

sudo usermod -aG apache ユーザー名

権限修正

sudo chgrp -R apache storage bootstrap/cache
sudo chmod -R 775 storage bootstrap/cache

setgid設定

sudo find storage bootstrap/cache -type d -exec chmod 2775 {} \;

ACL設定

sudo setfacl -R -m g:apache:rwx storage bootstrap/cache
sudo setfacl -R -d -m g:apache:rwx storage bootstrap/cache

確認

php artisan cache:clear
INFO  Application cache cleared successfully.

復旧。

タイトルとURLをコピーしました