Rails 7生产环境控制器异常无响应问题求助
问题描述
我有一个Rails 7.0.3.1应用,同时作为JS SPA的HTML服务器和对应API服务。开发环境下JSON API的错误能正确渲染(包含错误信息、调用栈等),但在生产环境或设置config.consider_all_requests_local = false时,Rails仅返回带500状态码的空白响应,完全不返回错误页面。尝试设置exceptions_app和配置路由均无效。
示例代码
Trips控制器
class TripsController < ApplicationController def show raise StandardError, 'Tripped and fell' end end
路由配置
Rails.application.routes.draw do get "/trip/:error" => 'trips#show' end
空白响应截图

版本信息
- Rails 7.0.3.1
- Ruby 3.0.2p107 (2021-07-07 revision 0db68f0233)
服务器控制台日志
=> Rails 7.0.3.1 application starting in development => Run `bin/rails server --help` for more startup options Puma starting in single mode... * Puma version: 5.6.4 (ruby 3.0.2-p107) ("Birdie's Version") * Min threads: 0 * Max threads: 1 * Environment: development * PID: 88888 * Listening on http://127.0.0.1:3000 * Listening on http://[::1]:3000 Use Ctrl-C to stop Started GET "/trip/500" for ::1 at 8888-88-88 88:88:88 -8888 ActiveRecord::SchemaMigration Pluck (1.2ms) SELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC Processing by TripsController#show as HTML Parameters: {"error"=>"500"} Completed 500 Internal Server Error in 8ms (ActiveRecord: 0.0ms | Allocations: 3293) StandardError (Tripped and fell): app/controllers/trips_controller.rb:6:in `show'
解决方法
1. 区分请求格式处理错误
Rails默认根据请求的Accept头返回对应格式的响应。从日志可见当前请求是HTML格式,需在控制器中统一处理不同格式的错误:
class ApplicationController < ActionController::Base rescue_from StandardError, with: :handle_error private def handle_error(exception) if request.format.json? render json: { error: exception.message, backtrace: exception.backtrace }, status: :internal_server_error else render plain: exception.message, status: :internal_server_error end end end
2. 配置自定义异常处理程序
在config/application.rb或对应环境配置文件中设置:
config.exceptions_app = ->(env) { ErrorsController.action(:show).call(env) }
创建ErrorsController:
class ErrorsController < ApplicationController def show status_code = request.env['action_dispatch.exception']&.status_code || request.status_code message = case status_code when 500 then '服务器内部错误' when 404 then '资源未找到' else '请求错误' end if request.format.json? render json: { error: message }, status: status_code else render plain: message, status: status_code end end end
同时在路由中添加:
get '/errors/:status', to: 'errors#show', constraints: { status: /\d{3}/ }
3. 确保生产环境静态错误页面存在
Rails生产环境默认使用public目录下的静态错误页面(如500.html、404.html),缺失会导致空白响应。可生成默认页面:
rails generate error_pages
或手动创建public/500.html并添加自定义内容。
4. 检查环境配置参数
确保config/environments/production.rb中:
config.consider_all_requests_local = false config.action_dispatch.show_exceptions = true
内容的提问来源于stack exchange,提问作者Eric Prostko
相关产品推荐
相关产品推荐

