Skip to content

current_user is a Hash in Rails 8.0.2 #5774

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
jasonperrone opened this issue Mar 26, 2025 · 8 comments
Open

current_user is a Hash in Rails 8.0.2 #5774

jasonperrone opened this issue Mar 26, 2025 · 8 comments

Comments

@jasonperrone
Copy link

I upgraded from Rails 8.0.1 to 8.0.2. Noticed the following:

  1. If the user was already logged out when going to the app and tried to login, they are immediately bounced back to the login screen with no error message and no errors in the logs.
  2. If the user already had a live session when I deployed the app with the upgrade from 8.0.1 -> 8.0.2, every action got an error because current_user is coming through ApplicationController as a Hash, not an Object.

LMK if I can give any other information. Ruby 3.4.2 btw.

@jasonperrone jasonperrone changed the title current_user is Hash in Rails 8.0.2 current_user is a Hash in Rails 8.0.2 Mar 26, 2025
@ivanthecrazy
Copy link

I have the same problem, appears sometimes in my test suite after rails upgrade.

@ivanthecrazy
Copy link

This is what seems to work for me (config/initializers/devise.rb):

Warden::Manager.serialize_into_session do |user|
  user.id
end

Warden::Manager.serialize_from_session do |id|
  User.find(id)
end

@jasonperrone
Copy link
Author

Interesting. I'll have to check my config and make sure I'm not doing anything weird.

@jasonperrone
Copy link
Author

The only thing I've seen is that when running in the production environment, Warden doesn't find any authentication strategies in its config, but it does in development. Still searching.

@caseyhelbling
Copy link

caseyhelbling commented Apr 16, 2025

I'm seeing the same thing -- Warden can't find valid mapping

  • Rails 8.02
  • Devise 4.9.4
     Failure/Error: before { sign_in user }
     
     RuntimeError:
       Could not find a valid mapping for #<User id: 1, email: [FILTERED], first_name: "Milford", last_name: "Bergstrom", created_at: "2025-04-16 16:44:38.469535000 +0000", updated_at: "2025-04-16 16:44:38.469535000 +0000", organization_id: 1, role_id: 1>
     # /usr/local/bundle/ruby/3.4.0/gems/devise-4.9.4/lib/devise/mapping.rb:46:in 'Devise::Mapping.find_scope!'
     # /usr/local/bundle/ruby/3.4.0/gems/devise-4.9.4/lib/devise/test/integration_helpers.rb:38:in 'Devise::Test::IntegrationHelpers#sign_in'
     # ./spec/requests/uploads_spec.rb:27:in 'block (4 levels) in <main>'

Adding

RSpec.configure do |config|
  %i(request controller).each do |type|
    config.before(:each, type: type) do
      Rails.application.try(:reload_routes_unless_loaded)
    end
  end

  config.before(:suite) do
    Devise.configure_warden!
  end
end

Warden::Manager.serialize_into_session do |user|
  user.id
end

Warden::Manager.serialize_from_session do |id|
  User.find(id)
end

To my rails_helper.rb fixes it for now.

@jasonperrone
Copy link
Author

So, I did figure something out. When I first upgraded to Rails 8.0.1 there was a bug which affected route loading. As a result, based on the conversation in #5716 , I changed config.reload_routes = false in config/initializers/devise.rb. Well after upgrading to 8.0.2 that configuration broke it. Merely commenting that out as it had been since I've started using Devise fixed this problem.

@RyanTG
Copy link

RyanTG commented Apr 29, 2025

For me, #5774 (comment) is what fixes it (thank you! I spent all day trying to figure this out).

Commenting or showing config.reload_routes = false doesn't impact it.

@mbaird
Copy link

mbaird commented May 13, 2025

We encountered intermittent test failures relating to this (in our case, current_admin returning a hash instead of an Admin instance).

A handy rspec --bisect narrowed it down to an RSpec controller block (controller { ... }) running before Rails routes are loaded. RSpec initializes a new RouteSet, triggering #draw and #finalize! before the main app’s routes have loaded. This configured Devise without any devise_for mappings from routes.rb.

Devise builds and caches "mappings" (e.g., for :admin) when devise_for is called in routes.rb. These mappings are used to configure Warden, including session serialization and deserialization.

Devise hooks into ActionDispatch::Routing::RouteSet#finalize! to register these mappings and configure Warden. Configuration can only happen once. If any code triggers #finalize! before Devise registers its mappings (e.g., due to test-specific routing), the Warden configuration is incomplete.

For us, the fix was to explicitly eager load the application routes before the controller test, ensuring Devise mappings are registered before #finalize! is called.

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

No branches or pull requests

5 participants