メシのタネ

メシのタネになる、Laravelや設計思想の技術配信サイト


WordPressページネーション404問題から学ぶ:深層デバッグと根本原因分析


  1. WordPress
  2. WordPressページネーション404問題から学ぶ:深層デバッグと根本原因分析

―― Redirection × Block Theme × canonical redirect が起こす“複合災害”を真っ正面から解剖する

はじめに

WordPress の「/page/2/ が 404 になる」──検索すると事例は山ほどあるのに、自分のサイトでは Redirection プラグインを無効化したら直る、という謎挙動。根本治療の鍵は、Apache から JavaScript まで 5 層 を縦断しながら実行パスを追うことだった。

この記事では実際のデバッグログを交え、直アクセスだけ 404、内部リンクは大丈夫 という一見オカルトなバグを、シンプルな原因へと収束させるプロセスを共有する。

備忘録なので、楽しくもないし誰の為にもなりませんが、俺のために残します。

たねまる

ねたばれすると、Redirectionに ^/.+/page/[0-9]+/?$ [F] っていう、
サイト全体の /page/N を 403/404  にするってアホなルール設定してたからだよ〜

第1章: WordPress深層部の動作原理

フック実行順序の真実

init → parse_request → pre_get_posts → wp
→ template_redirect → pre_handle_404

共に深淵に潜ったClaudeCodeくんの3行メモ

  • pre_handle_404 は 404 判定を止められる最後の関所。
  • redirect_canonical は 404 より前に走る。
  • template_redirect ならまだ HTTP ステータスを書き換えられる。

Block Theme のレンダリング機構

ファイル役割
template-canvas.php全ブロックテンプレートのエントリー
archive.htmlQuery Loop を含み、実データを描画
inherit 属性メインクエリを継承する生命線
enhancedPaginationJS ナビゲーションと直接アクセスで挙動がズレる要因

条件フラグのライフサイクル

// pre_get_posts 時点
is_category() → true
is_paged()    → true

// wp 時点(外部要因で破損)
is_category() → false   // canonical redirect が潰す
is_paged()    → false

ここでフラグが崩れた瞬間に起こること

  • $wp_query->posts が空配列になり、後段の pre_handle_404 で 404 判定が確定
  • Block Theme 側は wp-block-query-no-results を描画し、404 レイアウトが優先表示される
  • Interactivity API での JS ナビゲーション時はフラグが壊れないため、直アクセスと結果が食い違う

要チェックポイント

  1. redirect_canonical で URL が書き換わっていないか
  2. Redirection / SEO 系プラグインが pre_handle_404 で 404 を強制していないか
  3. Query Loop の inherit 属性が false のまま保存されていないか

第2章 実戦デバッグ技術

add_action('pre_get_posts', function($q){
    error_log('[PRE] cat='.(int)$q->is_category().' paged='.(int)$q->is_paged());
});

デバッグのポイント  

  • 1. pre_get_posts は メインクエリが初めて姿を現す 最速の地点。  
  • 2. ここで is_category() / is_paged() をログに残してベースラインを確定させる。  
  • 3. 後続フックのログと差分を比較すれば、どの処理がフラグを壊したか が一発でわかる。

HTTP レイヤーで確認

curl -I https://mikaduki.info/category/laravel/page/2/
  • X-Redirect-By: Redirection ← 犯人フラグ
  • HTTP/2 404 ← Apache で弾かれている
  • この時点で気づくべきだった。

二分探索式プラグイン切り分け

戦友ClaudeCodeくんのメモ

  1. 全部無効 → 正常 ⇒ プラグイン起因確定
  2. 半分有効 → 異常 ⇒ 範囲を半分に縮小
  3. Redirection 単独停止 → 正常 ⇒ 犯人特定

第3章 プラグイン連携の闇

Redirection がページ遷移に影響する 3 つの仕組み
―― 機能・フック・副作用を早見で把握 ――

何が動く?動く場所(フック/層)起こること・副作用
404 ログ記録機能pre_handle_404 / template_redirect$wp_query->is_404 = true / posts = [] → 画面が 404 に切り替わる
動的リダイレクト機能redirect_canonicalCore が出す canonical 301 を上書き、独自 301/302 を優先
.htaccess 直書き(Apache モード)Apache レイヤー(PHP 介さず)サーバーが直接 301/403 を返す → 超高速だが GUI で無効化しないと即反映

👹 Redirectionが2面性発揮

Interactivity API の落とし穴 ―― 同じ URL でも結果が変わる理由

アクセス方法ブラウザ側で起こること画面に現れる結果
内部リンクからの遷移
(<a href="…"> をクリック)
Interactivity API が “ページ差し替え” だけを実行。
JS が wp-block-query-no-results 要素を 非表示 にして投稿一覧だけを残す。
正常表示(404 ブロックは見えない)
URL を直接入力/リロードサーバー側でフルレンダリング。
テンプレートが 404 ブロック + 投稿一覧 を両方出力するが、JS はまだ実行されていない。
404 レイアウトが先に描画 → 投稿一覧が隠れ、404 画面に見える

第4章 根本原因分析の思考法

対症療法 vs 根本治療 — どちらを選ぶ?

対症療法(力技で 200 にする)

add_filter( 'status_header', fn( $h ) => str_replace( '404', '200', $h ) );

メリット

  • コード 1 行で即反映
  • テーマやプラグインの改変が一切不要

デメリット / 落とし穴

  • HTML には 404 ブロックが残る → 検索エンジンには 404 ページ扱い
  • キャッシュや AMP では 404 画面が再浮上することも
  • 別 URL で同症状が再発しやすい

根本治療(拒否ルールそのものを除去)

  • Redirection の 拒否正規表現 を GUI で「無効化」または「削除」 (ルール一覧 → チェック → Disable / Delete → 保存)

メリット

  • HTTP と HTML が完全に一致
  • 同じパターンの URL で問題が再発しない
  • SEO 的にも正しい 200 ページとしてクロールされる

デメリット / 注意点

  • ルールを見直す手間が少し必要
  • 「ページネーションは 1 ページ目に統合したい」場合は 301 で /page/n → / にリダイレクト する追加設定が要る

まとめ

  • 今日中にとにかく 404 表示を消したい → 対症療法で応急処置
  • SEO・再発防止を重視したい → 根本治療を選ぶのが最終的にラク

制御層の優先順位

  1. Apache/Nginx (.htaccess) – 最強
  2. WordPress Core (PHP)
  3. プラグイン
  4. テーマ (Block)
  5. JavaScript – 最弱

第5章 教訓と予防策

デバッグの黄金律

  1. ログを信じすぎるな – HTTP 200 でもブラウザは 404 を描くことがある
  2. SEO 系プラグインは常に疑え – canonical と 301/302 を重ねるから
  3. レイヤーを意識 – Apache → PHP → JS の順で確認

アーカイブ系のリダイレクト不具合のバグフィックス

  • Query Loop では inherit:true を明示
  • リダイレクト系プラグイン導入後は .htaccess 差分チェック
  • 404 ルールを設ける前に 正規表現がページネーションを潰さないかテスト

犯人は自分

Redirection を外そうかと腹を括り、エクスポート機能で .htaccess 用ルールを吐き出してみたら──

^/.+/page/[0-9]+/?$        [F]

ページネーションをまるごと葬る “[F] 行” が、なんと最上段に鎮座。

おかげで原因が即座に特定でき、その 1 行を削除して無事復旧しました。

おわりに

パーマリンクを変更して以降、カテゴリーページの 2 ページ目に進めない不具合がずっと残ったままでした。閲覧が少ないこともあり後回しにしていたのですが、休日にまとまった時間が取れたうえに ChatGPT-o3 と ClaudeCode という新兵器を入手したので、一気に片付けようと着手。ところが想像以上に手こずる結果に――。

「パッチを当てれば済むだろ」と高をくくっていたら、結局はテーマの深部まで手を入れる羽目に。
「もう限界、Apache のリダイレクトで力技に切り替えよう」と覚悟を決めた瞬間、あの page/n 禁止ルール が目に飛び込んできた──まるで見えざる神の手に救われた気分だった・・・。

この体験で痛感したのは、「いきなりコードの深淵に飛び込まない」こと。
まずは 設定・プラグイン・サーバー層 を一通り洗い、ログを取り、可能性を潰してから手を入れる──それだけで余計な沼を避けられます。
私のしくじりが、みなさんの“時間節約ハック”になれば幸いです。

ページネーションが 404 になるとき、まず何を確認すればいい?

1) .htaccess に /page/ 系の拒否ルールがないか 
2) redirect_canonical を潰すプラグイン(Redirection など)が動いていないか 
3) Block Theme の Query Loop で inherit:true が設定されているか、の順でチェックすると早いです。

Apache (.htaccess) モードに切り替えるメリットは?

  1. 301/302 を Apache が直接処理 → PHP 起動ゼロで高速
  2. WordPress フックを通らないため canonical/404 介入バグと無縁
  3. ルール追加は GUI で OK、保存すると .htaccess が即更新

page/n 絶許ルール の見つけ方は?

Redirection 画面の検索ボックスに page/[0-9] と入力。

page/n 絶許ルール の見つけ方は?

Redirection 画面の検索ボックスに page/[0-9] と入力。

対症療法で一瞬だけ 404 を消すには?

add_filter( 'status_header', fn( $h ) => str_replace( '404', '200', $h ) );
# 応急処置。HTML には 404 ブロックが残るので SEO 目的なら根本治療を。


コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

This site uses Akismet to reduce spam. Learn how your comment data is processed.