【完全版】Rails「ActionController::RoutingError」エラーの原因と対処法|No route matches を徹底解説
Ruby on Rails で頻発するエラー:
ActionController::RoutingError (No route matches [GET] "/users/profile")
ActionController::RoutingError (No route matches [POST] "/api/v1/users")
ActionController::RoutingError (No route matches [GET] "/assets/application-abc123.css")
No route matches {:action=>"show", :controller=>"users"}, missing required keys: [:id]
ActionController::RoutingError は「指定されたURLに該当するルートが存在しない」場合に発生します。Rails のリクエスト処理の最初の関門で起きるエラーで、
- URL の typo が原因?
- routes.rb の設定が間違っている?
- HTTPメソッドが違う?
rescue_fromで捕まえられない理由は?- 本番でカスタム404を表示したい
- アセットでよく出るのは何?
- セキュリティ的な対策は?
など、初学者から実務者まで遭遇する問題です。
本記事では、ActionController::RoutingError のすべての原因と対処法を、現場で即使えるトラブルシューティングとして整理します。エラーの本質、rails routes の活用、catch-all route と exceptions_app、RecordNotFoundとの違い、APIモード対応、404ページカスタマイズ、デバッグ手法、FAQまで完全網羅。この1本でRails ルーティングエラーに自信を持って対処できます。
- 1. 結論:今すぐ試すべき3ステップ
- 2. まず押さえる:エラーの本質
- 3. なぜ rescue_from RoutingError は効かないのか
- 4. 解決策1:catch-all route
- 5. 解決策2:exceptions_app(推奨)
- 6. 解決策3:public/404.html(最も簡易)
- 7. 発生原因と対処パターン
- 8. rails routes コマンドの活用
- 9. APIモードでのカスタム404レスポンス
- 10. セキュリティ・ログ管理
- 11. 404ページの動的カスタマイズ
- 12. トラブルシューティング
- 13. 関連エラーとの違い
- 14. よくある質問(FAQ)
- 14.1. Q1. なぜ rescue_from RoutingError が動かない?
- 14.2. Q2. 開発環境で404画面を確認したい
- 14.3. Q3. catch-all route と exceptions_app どちらを使うべき?
- 14.4. Q4. catch-all route がエンジンのルートと競合します
- 14.5. Q5. APIで404をJSON形式で返す
- 14.6. Q6. 404 のログを抑制したい
- 14.7. Q7. リダイレクトで対処する
- 14.8. Q8. テストで RoutingError を確認する
- 14.9. Q9. POST/DELETE が GET に変換される
- 14.10. Q10. アセットで404が頻発します
- 14.11. Q11. routes.rb が大きすぎて管理が困難
- 14.12. Q12. RoutingError のエラーレポートに自分のパスを含める
- 15. 参考リンク・関連資料
- 16. まとめ
結論:今すぐ試すべき3ステップ
時間がない方向けに、まず実施すべき手順を示します。
ステップ1:エラーから情報を取得
ActionController::RoutingError (No route matches [GET] "/users/profile")
↑ ↑
メソッド リクエストURL
→ 「GETで /users/profile にアクセスしたが、対応するルートが無い」
ステップ2:現在のルート確認
bin/rails routes
# または
bin/rails routes | grep users
該当するルートがあるか確認。
ステップ3:原因別に対処
A. ルート未定義 → routes.rb に追加
# config/routes.rb
get "users/profile", to: "users#profile"
# または resources
resources :users do
get :profile, on: :collection
end
B. HTTPメソッド違い → メソッド合わせる
<!-- GET なのに POST で送っている等 -->
<%= form_with url: users_path, method: :post do %>
C. typo → URL を修正
# /users/profile(正) vs /user/profile(誤)
詳細は以下で解説します。
まず押さえる:エラーの本質
ActionController::RoutingError とは
Rails のルーティングミドルウェアがリクエストURLに対応するルートを見つけられない時に発生する例外。
リクエスト → Rack → Routing → コントローラ
↓
該当ルート無し
↓
ActionController::RoutingError
Rails の自動404変換
ApplicationController のデフォルト動作として、Rails は以下のように扱う:
# rails/actionpack/lib/action_dispatch/middleware/exception_wrapper.rb
ActionDispatch::ExceptionWrapper.rescue_responses
# => {
# "ActiveRecord::RecordNotFound" => :not_found,
# "ActionController::RoutingError" => :not_found, ← これ
# ...
# }
つまり、本番環境では自動的に 404 になります。
開発環境 vs 本番環境
| 環境 | RoutingError の挙動 |
|---|---|
| development | 詳細エラー画面(routes 一覧表示) |
| test | テスト失敗 |
| production | 自動的に 404 ページ表示 |
RecordNotFound との違い
| 観点 | RoutingError | RecordNotFound |
|---|---|---|
| 発生レイヤー | ルーティング | コントローラ + Model |
| 発生理由 | URLにマッチするroute無し | レコードが見つからない |
| rescue_from | 効かない(後述) | 効く |
| 本番でのデフォルト | 404 | 404 |
| 例 | /nonexistent_path | /users/999 |
詳しい RecordNotFound 対策はActiveRecord::RecordNotFound の記事を参照。
なぜ rescue_from RoutingError は効かないのか
これは多くの開発者が引っかかる罠です。
期待する書き方
class ApplicationController < ActionController::Base
rescue_from ActionController::RoutingError, with: :route_not_found
# ↑ これでは動かない!
private
def route_not_found
render template: "errors/not_found", status: :not_found
end
end
なぜ効かないか
RoutingError はコントローラに到達する前にミドルウェアレベルで発生するため、ApplicationControllerのrescue_fromでは捕まえられません。
[リクエスト]
↓ Rack 経由
[ActionDispatch::Routing] ← ここで RoutingError 発生
↓ ルートマッチ
[ApplicationController] ← rescue_from が動くのはここ
ミドルウェアで例外が出る前に、コントローラまで到達しないという仕組み上の問題。
解決策
| 方法 | 特徴 |
|---|---|
| catch-all route | routes.rb で全URLを受ける |
| exceptions_app | Rails標準の例外ハンドラ |
| public/404.html | 静的404ページ |
詳細は以下で解説します。
解決策1:catch-all route
config/routes.rb の末尾にcatch-all を置き、すべての未マッチURLをコントローラに送る方法。
基本実装
# config/routes.rb
Rails.application.routes.draw do
root "home#index"
resources :users
resources :posts
# ... 他のルート ...
# 最後に catch-all
match "*unmatched", to: "errors#not_found", via: :all
end
# app/controllers/errors_controller.rb
class ErrorsController < ApplicationController
def not_found
render status: :not_found
end
end
<%# app/views/errors/not_found.html.erb %>
<h1>404 - ページが見つかりません</h1>
<p>お探しのページは見つかりませんでした。</p>
<%= link_to "トップへ", root_path %>
glob パターンの注意点
match "*unmatched", to: "errors#not_found", via: :all
*unmatched: 残りの全パスをキャプチャvia: :all: GET/POST/PUT/PATCH/DELETE すべてに対応
resources より後に置く
# ❌ 上に置くと resources を上書きしてしまう
match "*unmatched", to: "errors#not_found", via: :all
resources :users # ← これがマッチしない
# ✅ 必ず最後
resources :users
match "*unmatched", to: "errors#not_found", via: :all
config.after_initialize で append
エンジンgemのroutesがある場合、それらの後に追加するには:
# config/application.rb
config.after_initialize do |app|
app.routes.append { match "*path", to: "errors#not_found", via: :all }
end
prepend ではなく append を使うのがポイント。
解決策2:exceptions_app(推奨)
Rails 3.2 以降の正式な方法。例外を独自のRack アプリにルーティング。
基本セットアップ
# config/application.rb
config.exceptions_app = self.routes
これでルーティング自体をエラーハンドラとして使用可能に。
# config/routes.rb
Rails.application.routes.draw do
# 通常のルート
root "home#index"
resources :users
# ...
# エラーページのルート(exceptions_app で使われる)
match "/404", to: "errors#not_found", via: :all
match "/422", to: "errors#unprocessable_entity", via: :all
match "/500", to: "errors#internal_server_error", via: :all
end
# app/controllers/errors_controller.rb
class ErrorsController < ApplicationController
layout "error"
skip_before_action :authenticate_user!, raise: false # 認証スキップ
def not_found
@exception = request.env["action_dispatch.exception"]
@original_path = request.env["action_dispatch.original_path"]
render status: :not_found
end
def unprocessable_entity
render status: :unprocessable_entity
end
def internal_server_error
render status: :internal_server_error
end
end
catch-all との違い
| 方法 | メリット | デメリット |
|---|---|---|
| catch-all route | シンプル | 認証ミドルウェアやBefore Actionの影響を受ける |
| exceptions_app | Rails標準、認証等の干渉なし | 設定が若干複雑 |
本番運用なら exceptions_app 推奨。
例外情報の取得
def not_found
@exception = request.env["action_dispatch.exception"]
@original_path = request.env["action_dispatch.original_path"]
@original_request = request.env["action_dispatch.original_request"]
Rails.logger.warn "404: #{@original_path}"
render status: :not_found
end
解決策3:public/404.html(最も簡易)
何も設定しなくても、Rails は public/404.html を404レスポンスとして返します:
<!-- public/404.html -->
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>404 - ページが見つかりません</title>
<link rel="stylesheet" href="/404.css">
</head>
<body>
<h1>404 - ページが見つかりません</h1>
<p>お探しのページは存在しません。</p>
<a href="/">トップへ戻る</a>
</body>
</html>
メリット:
- 設定不要
- 静的ファイルなのでサーバー負荷ゼロ
- Rails未起動でも返せる(Webサーバー側で配信)
デメリット:
- 動的処理ができない(i18n、メッセージカスタマイズ等)
- レイアウト統一が難しい
Webサーバー側での配信
Nginx などで配信:
location / {
try_files $uri $uri/ @app;
error_page 404 /404.html;
}
発生原因と対処パターン
原因1:未定義のURL
GET /users/profile
ActionController::RoutingError (No route matches [GET] "/users/profile")
確認:
bin/rails routes | grep profile
対処: routes.rb に追加
# config/routes.rb
get "users/profile", to: "users#profile"
# または
resources :users do
collection do
get :profile
end
end
原因2:HTTPメソッドの不一致
ActionController::RoutingError (No route matches [POST] "/users/1")
POSTで送っているが、/users/1はPATCHやPUTを期待している:
bin/rails routes | grep users
# user PUT|PATCH /users/:id ... ← PUT/PATCH が必要
対処: フォームのメソッドを修正
<%= form_with url: user_path(@user), method: :patch do %>
原因3:resources ネスティングの違い
ActionController::RoutingError (No route matches [GET] "/users/1/posts/2")
bin/rails routes | grep posts
# 単独の /posts/:id しかない
対処: nested resources で定義
resources :users do
resources :posts
end
原因4:URL helperの誤用
<%= link_to "Edit", user_path(@user) %>
<%# user_path には id が必要! %>
エラー:
No route matches {:action=>"show", :controller=>"users"}, missing required keys: [:id]
対処:
<%# @user が nil でないか確認 %>
<%= link_to "Edit", user_path(@user) if @user %>
<%# または new_user_path 等を使う %>
<%= link_to "New User", new_user_path %>
原因5:フォーマット制約の不一致
# config/routes.rb
get "/users/:id", to: "users#show", format: :json
ActionController::RoutingError (No route matches [GET] "/users/1.html")
# HTMLが拒否される
対処: 制約を緩める or 明示
get "/users/:id", to: "users#show" # 全フォーマット許可
# または
get "/users/:id", to: "users#show", defaults: { format: :json }
原因6:constraints の制限
constraints subdomain: "api" do
resources :users
end
api.example.com 以外でのアクセスでルーティングエラー。
対処: subdomain や constraints の正当性確認。
原因7:アセットパスの間違い
ActionController::RoutingError (No route matches [GET] "/assets/application.css")
これは:
config.public_file_server.enabledが false- precompile していない
- digest 付きファイル名の不整合
- アセットパイプライン(Sprockets/Propshaft)の設定問題
対処:
# config/environments/production.rb
config.public_file_server.enabled = true
# または環境変数 RAILS_SERVE_STATIC_FILES=true
RAILS_ENV=production bin/rails assets:precompile
Propshaft 使い方の記事も参照。
原因8:concerns やネスト深さの問題
resources :users do
concerns :commentable
end
concern :commentable do
resources :comments
end
/users/1/comments/2/replies のように深くなると、ルートを正確に定義しないとエラー。
bin/rails routes でルート構造確認推奨。
原因9:DELETE/PATCH リクエストのCSRF問題
ActionController::RoutingError (No route matches [GET] "/users/1")
DELETE/PATCH リクエストがGETに変換されている場合。これは:
- フォームのCSRF token不足
- AJAX で適切なヘッダーが送られていない
CSRF関連エラーは別記事「ActionController::InvalidAuthenticityToken」参照。
原因10:本番デプロイ後のキャッシュ
Webサーバー(Nginx等)の routes キャッシュや、CDN キャッシュが古いことが原因。
対処: キャッシュクリア、サーバー再起動。
rails routes コマンドの活用
ルーティング問題の調査に必須のコマンド。
基本
bin/rails routes
出力例:
Prefix Verb URI Pattern Controller#Action
root GET / home#index
users GET /users(.:format) users#index
POST /users(.:format) users#create
new_user GET /users/new(.:format) users#new
edit_user GET /users/:id/edit(.:format) users#edit
user GET /users/:id(.:format) users#show
PATCH /users/:id(.:format) users#update
PUT /users/:id(.:format) users#update
DELETE /users/:id(.:format) users#destroy
| 列 | 意味 |
|---|---|
| Prefix | URL helper の prefix(user_path等) |
| Verb | HTTPメソッド |
| URI Pattern | URL パターン |
| Controller#Action | 処理するコントローラとアクション |
フィルタリング
# 特定のキーワードを含むルート
bin/rails routes -g user
# 特定のコントローラ
bin/rails routes -c users
# 特定のフォーマット
bin/rails routes --format json
ブラウザでの確認
開発環境で http://localhost:3000/rails/info/routes にアクセス:
- 検索可能なルート一覧
- 各ルートの詳細
詳細表示
bin/rails routes --expanded
各ルートが複数行で詳細表示される。
APIモードでのカスタム404レスポンス
JSON API では JSON 形式の404を返したい。
exceptions_app 方式
# config/routes.rb
Rails.application.routes.draw do
namespace :api do
namespace :v1 do
resources :users
end
end
# エラー用
match "/404", to: "errors#not_found", via: :all
match "/500", to: "errors#internal_server_error", via: :all
end
# config/application.rb
config.exceptions_app = self.routes
# app/controllers/errors_controller.rb
class ErrorsController < ActionController::API
def not_found
render json: {
error: {
type: "NotFound",
message: "リクエストされたリソースが見つかりません"
}
}, status: :not_found
end
def internal_server_error
render json: {
error: {
type: "InternalServerError",
message: "サーバーエラーが発生しました"
}
}, status: :internal_server_error
end
end
catch-all route 方式(APIモード)
# config/routes.rb
Rails.application.routes.draw do
namespace :api do
namespace :v1 do
resources :users
end
end
# JSONレスポンス用 catch-all
match "*unmatched", to: "errors#not_found", via: :all
end
class ErrorsController < ApplicationController
def not_found
respond_to do |format|
format.json { render json: { error: "Not Found" }, status: :not_found }
format.html { render template: "errors/not_found", status: :not_found }
format.any { head :not_found }
end
end
end
Rails-API モード固有
class Api::ApplicationController < ActionController::API
# ApplicationController を継承しない場合
end
セキュリティ・ログ管理
Bot による大量404
GET /wp-admin
GET /.env
GET /admin
GET /phpmyadmin
このような攻撃的スキャンは日常的に発生。RoutingError ログが大量に出ます。
ログレベル調整
# config/application.rb
config.log_level = :info # debugから上げる
または、RoutingError のログだけ抑制:
class ErrorsController < ApplicationController
def not_found
path = request.env["action_dispatch.original_path"]
# 攻撃的なパターンは WARN レベルに下げる
if suspicious_path?(path)
Rails.logger.warn "Suspicious 404: #{path}"
else
Rails.logger.info "404: #{path}"
end
render status: :not_found
end
private
def suspicious_path?(path)
path =~ /(wp-admin|\.env|phpmyadmin|admin\/login)/i
end
end
エラートラッカーで除外
Sentry/Rollbar/Honeybadger 等で RoutingError を除外(ノイズ削減):
# config/initializers/sentry.rb
Sentry.init do |config|
config.excluded_exceptions += [
"ActionController::RoutingError",
"ActiveRecord::RecordNotFound"
]
end
Rack-Attack でレート制限
# config/initializers/rack_attack.rb
class Rack::Attack
# 1分間に60リクエストまで
throttle("req/ip", limit: 60, period: 1.minute) do |req|
req.ip
end
# 不審なパスをブロック
blocklist("malicious_paths") do |req|
req.path =~ /(\.env|wp-admin|phpmyadmin)/i
end
end
404ページの動的カスタマイズ
i18n 対応
<%# app/views/errors/not_found.html.erb %>
<h1><%= t("errors.not_found.title") %></h1>
<p><%= t("errors.not_found.description") %></p>
<%= link_to t("errors.not_found.back_home"), root_path %>
# config/locales/ja.yml
ja:
errors:
not_found:
title: "ページが見つかりません"
description: "お探しのページは削除されたか、URLが間違っている可能性があります。"
back_home: "ホームに戻る"
検索ボックス表示
<%= form_with url: search_path, method: :get, class: "search-form" do %>
<%= text_field_tag :q, params[:q], placeholder: "サイト内検索" %>
<%= submit_tag "検索" %>
<% end %>
関連リンクの提案
def not_found
@suggestions = SuggestionService.find_similar(request.path)
render status: :not_found
end
<% if @suggestions.any? %>
<h2>もしかして?</h2>
<ul>
<% @suggestions.each do |link| %>
<li><%= link_to link.title, link.url %></li>
<% end %>
</ul>
<% end %>
アナリティクス埋め込み
<script>
gtag('event', 'page_not_found', {
'event_category': 'error',
'event_label': '<%= @original_path %>'
});
</script>
404発生パスを分析して、リンク切れの修正に役立てます。
トラブルシューティング
rescue_from RoutingError が効かない
前述の通り、これは Rails の仕様。exceptions_app または catch-all route を使ってください。
Production で 500 になる(404にならない)
# config/environments/production.rb
config.exceptions_app = self.routes # ← 設定済みか確認
ErrorsController のアクションでエラーが起きていないか確認。
Development でも404ページを見たい
# config/environments/development.rb
config.consider_all_requests_local = false
これで開発環境でも本番と同じ404ページが表示されます。
Webpackerやアセットで頻発する
開発時:
# config/environments/development.rb
config.assets.compile = true
本番:
bin/rails assets:precompile
static_asset を返す設定
# config/environments/production.rb
config.public_file_server.enabled = true
# または環境変数
# RAILS_SERVE_STATIC_FILES=true
CDN/Nginx で配信するなら無効でOK。
Devise や認証ライブラリとの競合
class ErrorsController < ApplicationController
skip_before_action :authenticate_user!, raise: false
# before_action のスキップを忘れずに
end
エラーページで認証要求すると無限ループに。
test 環境で routes 関連エラー
# spec/rails_helper.rb
config.before(:each) do
Rails.application.reload_routes!
end
routes.rb 変更後に test が古いルートを参照していないか確認。
POST/PATCH/DELETE がすべて GET になる
CSRF token の不足が原因の可能性。フォームでは:
<%= form_with model: @user do |f| %>
<%# 自動でCSRFトークン付与 %>
<% end %>
API では:
class Api::ApplicationController < ActionController::API
# ActionController::API は CSRFチェック自動スキップ
end
関連エラーとの違い
ActiveRecord::RecordNotFound
URLとマッチするrouteはあるが、DBレコードが無い。詳細はRecordNotFoundの記事。
# /users/999 → routes はマッチ、Userレコードが無い
User.find(999)
# => ActiveRecord::RecordNotFound
NoMethodError
ルーティング後のコントローラ内でnilエラー。nil:NilClass記事参照。
AbstractController::ActionNotFound
ルートはあるが、コントローラのアクションが未定義。
# routes
get "users/special", to: "users#special_action"
# UsersController
# def special_action が定義されていない
# => AbstractController::ActionNotFound
ActionController::ParameterMissing
ルートにマッチしたが、必須パラメータが不足。
params.require(:user).permit(:name)
# params[:user] が無い
# => ActionController::ParameterMissing
違いの早見表
| 例外 | レイヤー | 例 |
|---|---|---|
| RoutingError | ルーティング | URL未定義 |
| ActionNotFound | コントローラ | アクション未定義 |
| RecordNotFound | Model | DBレコード不在 |
| ParameterMissing | コントローラ | 必須params不足 |
よくある質問(FAQ)
Q1. なぜ rescue_from RoutingError が動かない?
RoutingError は ApplicationController に到達する前のミドルウェアで発生するため。exceptions_app または catch-all route を使ってください。
Q2. 開発環境で404画面を確認したい
# config/environments/development.rb
config.consider_all_requests_local = false
これで本番と同じ404ページが見られます。
Q3. catch-all route と exceptions_app どちらを使うべき?
| 状況 | 推奨 |
|---|---|
| 単純な404 | catch-all(簡単) |
| 認証ミドルウェアあり | exceptions_app |
| Rails標準推奨 | exceptions_app |
業務アプリでは exceptions_app 推奨。
Q4. catch-all route がエンジンのルートと競合します
# config/application.rb で append
config.after_initialize do |app|
app.routes.append { match "*path", to: "errors#not_found", via: :all }
end
これで最後に追加され、エンジンルートを上書きしません。
Q5. APIで404をJSON形式で返す
class ErrorsController < ActionController::API
def not_found
render json: { error: "Not Found" }, status: :not_found
end
end
Q6. 404 のログを抑制したい
def not_found
path = request.env["action_dispatch.original_path"]
Rails.logger.info "404: #{path}" # debugではなくinfoに
render status: :not_found
end
Sentry等のトラッカーで ActionController::RoutingError を除外設定も推奨。
Q7. リダイレクトで対処する
def not_found
redirect_to root_path, alert: "ページが見つかりません"
end
ただし SEO 的には HTTP 404 を正しく返す方が良いです。
Q8. テストで RoutingError を確認する
# RSpec
it "存在しないパスで404" do
expect { get "/nonexistent" }.to raise_error(ActionController::RoutingError)
end
# または raise_error しない形に
it "404 を返す" do
get "/nonexistent"
expect(response).to have_http_status(:not_found)
end
config.action_dispatch.show_exceptions = true の設定や、test 用の error route 設定が必要な場合あり。
Q9. POST/DELETE が GET に変換される
CSRF token が原因のことが多い:
<%# form_with は自動でCSRFトークン付与 %>
<%= form_with model: @user do |f| %>
<% end %>
Turbo を使う場合は data-turbo-method も使えます:
<%= link_to "削除", user_path(@user), data: { turbo_method: :delete } %>
Q10. アセットで404が頻発します
Production 環境の設定確認:
config.public_file_server.enabled = true
または、CDN/Nginxで静的ファイルを配信する構成に。
Propshaft 使い方の記事も参考に。
Q11. routes.rb が大きすぎて管理が困難
Rails 6+ の機能で分割可能:
# config/routes.rb
Rails.application.routes.draw do
draw :api # config/routes/api.rb を読み込む
draw :admin # config/routes/admin.rb
# 通常のルート
root "home#index"
end
# config/routes/api.rb
namespace :api do
namespace :v1 do
resources :users
end
end
Q12. RoutingError のエラーレポートに自分のパスを含める
exceptions_app 内で:
def not_found
@path = request.env["action_dispatch.original_path"]
Rails.logger.warn "404 for: #{@path}"
Sentry.capture_message("404: #{@path}") if Rails.env.production?
render status: :not_found
end
不要に追跡する必要はありませんが、急増したパスの調査に有用。
参考リンク・関連資料
Rails 公式
- Rails Routing from the Outside In(Guide) – ルーティング公式
- Configuring Rails Applications(Guide) – exceptions_app
- The Rails Command Line(Guide) – rails routes
ライブラリ
- Rack::Attack – リクエスト制限・ブロック
- Sentry / Rollbar / Bugsnag – エラートラッキング
関連記事(本サイト)
- undefined method nil:NilClass エラー対処 – nilエラー
- ActiveRecord::RecordNotFound エラー対処 – レコード不在404
- Rails 8 アップグレードガイド – Rails 8 全般
- Solid Queue 使い方 – Rails 8 Solid Trifecta
- Propshaft 使い方 – アセット関連の404対策
- MySQL 1146 Table doesn’t exist – DBエラー
まとめ
ActionController::RoutingError は Rails ルーティング層で発生する例外。要点を再整理します。
- 本質: URLにマッチするルートが無い、ルーティング層で発生
- rescue_from は効かない: ミドルウェア層で発生するため
- 対処:
- catch-all route: 簡易だが認証等の影響あり
- exceptions_app: Rails標準推奨、認証等の干渉なし
- public/404.html: 最も簡易
- rails routes: ルート確認の必須コマンド
- 本番自動404変換: production環境では自動的に404
- 発生原因: 未定義URL、HTTPメソッド不一致、resources設定、URL helper誤用、フォーマット制約、アセット
- API: JSON形式の404レスポンスを設定
- セキュリティ: 攻撃的スキャンを Rack-Attack 等で制限
- 404ページ: i18n、検索ボックス、サジェスト等で UX 向上
- RecordNotFound との違い: ルーティング層 vs Model層
これらの知識は、Rails アプリの設計・本番運用・SEO最適化・セキュリティ強化など、あらゆる場面で活用できます。本記事をブックマークしておけば、ActionController::RoutingError に遭遇した時の対応が大幅に効率化されます。
本記事は2026年6月時点の情報をもとに、Ruby on Rails 7.x / 8.x での動作確認・公式ドキュメントに基づき作成しています。Rails のバージョンによって挙動が異なる場合があるため、最新の情報はRails公式ガイドもあわせてご確認ください。
-
前の記事
「nginx: [emerg] bind() to 0.0.0.0:80 failed」の原因と解決方法 2026.07.02
-
次の記事
MySQL「Access denied for user ‘root’@’localhost’」の原因と解決方法|パスワードリセット完全ガイド 2026.07.02
コメントを書く