Skip to content

Conversation

@taketo1113
Copy link

Background

In Rack v3.1.0, the symbol for HTTP status code 422 was changed from :unprocessable_entity to :unprocessable_content.
As a result, when using rack 3.2 with the following configuration in config/initializers/devise.rb, a warning is shown on login failure:

# config/initializers/devise.rb
Devise.setup do |config|
  ...
  config.responder.error_status = :unprocessable_entity

Warning message:

/path-to-app/vendor/bundle/ruby/3.4.0/gems/devise-4.9.4/lib/devise/failure_app.rb:80: warning: Status code :unprocessable_entity is deprecated and will be removed in a future version of Rack. Please use :unprocessable_content instead.

This warning can be resolved by updating the config as follows:

# config/initializers/devise.rb
Devise.setup do |config|
  ...
+  config.responder.error_status = :unprocessable_content
-  config.responder.error_status = :unprocessable_entity
  • System configuration
    • ruby: 3.4.5
    • rails: 8.0.2.1
    • devise: 4.9.4

Note that this warning continues to occur even after applying the following Rails patch:

Details

This Pull Request fixes the root cause of the warning by adjusting the generated config during $ rails generate devise:install depending on the rack version.
With this change, newly generated Devise configs will no longer produce warnings.
( Fix #5791 )

# config/initializers/devise.rb
Devise.setup do |config|
  ...
+  config.responder.error_status = :unprocessable_content
-  config.responder.error_status = :unprocessable_entity

For rack 3.1 and higher, this change uses :unprocessable_content instead of :unprocessable_entity.
For rack 3.0 and below, it continues to use :unprocessable_entity.

Additional information

DeviseController: Error Status

Controllers under app/controllers/devise have also been updated to return the status defined in config.responder.error_status when handling errors.
If config.responder.error_status remains at its default value (:ok), the status falls back to the rack version:

  • :unprocessable_content for rack 3.1+
  • :unprocessable_entity for rack 3.0 and below
# app/controllers/devise/confirmations_controller.rb
...
       respond_with_navigational(resource){ redirect_to after_confirmation_path_for(resource_name, resource) }
     else
-      # TODO: use `error_status` when the default changes to `:unprocessable_entity`.
-      respond_with_navigational(resource.errors, status: :unprocessable_entity){ render :new }
+      # Use `error_status` when the default changes to `:unprocessable_content` (or `:unprocessable_entity`).
+      respond_with_navigational(resource.errors, status: (Devise.responder.error_status != :ok) ? Devise.responder.error_status : Rack::Utils::SYMBOL_TO_STATUS_CODE.key(422) ){ render :new }
     end
   end

Symbol selection between :unprocessable_entity and :unprocessable_content

The symbol selection between :unprocessable_entity and :unprocessable_content is determined by Rack:

The behavior of Rack::Utils::SYMBOL_TO_STATUS_CODE.key(422) depends on the Rack version:

Rack::Utils::SYMBOL_TO_STATUS_CODE.key(422)
=> :unprocessable_content # rack 3.1 or higher
=> :unprocessable_entity # rack 3.0 and below

The code for Rack::Utils::SYMBOL_TO_STATUS_CODE can be found here:
https://github.com/rack/rack/blob/v3.2.1/lib/rack/utils.rb#L564-L566
https://github.com/rack/rack/blob/2.0.0/lib/rack/utils.rb#L581-L583

…ity in confirmations and unlocks controllers
For rack 3.1 and higher, devise config uses `:unprocessable_content` instead of `:unprocessable_entity`.
For rack 3.0 and below, it continues to use `:unprocessable_entity`.
@otherjustin
Copy link

+1 works on my setup and tests pass

@carlosantoniodasilva carlosantoniodasilva added this to the 5.0 milestone Oct 31, 2025
Copy link
Member

@carlosantoniodasilva carlosantoniodasilva left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks. I think I'll have to handle this better / somehow on responders too for a more complete fix, and the controller code / conditionals seem overly verbose tbh, for anyone looking at it, so I'll need to think about it some, but I appreciate the PR! I don't have any immediate feedback other than I'll take a better look and report back when possible.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

Use unprocessable_content instead of unprocessable_entity for 422 status codes

4 participants