#5830·devise

[Bug] Rememberable strategy not invoked on first request after server restart in development (eager_load=false)

Author: milk1000ccCreated Mar 16, 2026Updated Mar 16, 2026

Environment

  • Devise: 5.0.2
  • Rails: 8.1.2
  • Ruby: 4.0.1
  • Warden: 1.2.9
  • eager_load: false (development default)

Summary

After restarting both the Rails server and the browser, the first request to the app results in current_user: nil even though a valid remember_user_token cookie exists. Reloading the page immediately restores the authenticated state. This happens only in development (eager_load=false). Setting eager_load=true or expire_after on the session store prevents the issue.

Steps to Reproduce

  1. Sign in with remember_me: true
  2. Restart the Rails server
  3. Restart the browser (clears session cookie, but remember_me cookie persists)
  4. Open the site → renders as logged out (current_user: nil)
  5. Reload the page → logged in correctly

Debug Findings

Added the following to ApplicationController:

ruby
before_action :debug_auth

def debug_auth
  Rails.logger.debug "remember cookie: #{cookies['remember_user_token'].present?}"
  Rails.logger.debug "warden session:  #{session['warden.user.user.key'].inspect}"
  Rails.logger.debug "current_user:    #{current_user.inspect}"
  Rails.logger.debug "winning_strategy: #{request.env['warden'].winning_strategy.inspect}"
end

First request (after server + browser restart):

remember cookie: true
warden session:  nil
current_user:    nil
winning_strategy: nil

Second request (reload):

remember cookie: true
warden session:  nil   # still nil — recovery is via rememberable
current_user:    #<User id: 1 ...>
winning_strategy: #<Devise::Strategies::Rememberable ...>

Key observations:

  • Warden::Strategies._strategies.key?(:rememberable)true (globally registered)
  • winning_strategy is nil on the first request, meaning :rememberable is not being tried by Warden for the :user scope on the first request
  • Explicitly calling warden.authenticate(:rememberable, scope: :user) in a before_action resolves the issue entirely

Root Cause Hypothesis

In development, eager_load=false means the User model is not loaded at boot time. The User model's devise :rememberable declaration is what triggers registration of :rememberable into Warden's default_strategies for the :user scope.

In Devise v5, initialization-time autoloading was removed (to comply with Zeitwerk's prohibition on autoloading during initialization). As a result, on the first request after a server restart, User has not yet been loaded → :rememberable is not in default_strategies[:user] → Warden does not attempt the strategy → current_user returns nil.

By the second request the constant has been autoloaded (as a side effect of the first request's processing), so :rememberable is registered and authentication works.

This did not reproduce with eager_load=true, confirming the autoloading timing as the root cause.

Workaround

ruby
# app/controllers/application_controller.rb
before_action :restore_remember_me_session

private

def restore_remember_me_session
  return if warden.authenticated?(:user)
  return if cookies["remember_user_token"].blank?
  warden.authenticate(:rememberable, scope: :user)
end

Expected Behavior

:rememberable should be attempted on the first request regardless of whether eager_load is enabled, as long as the remember_user_token cookie is present.

Notes

  • This is easy to miss: it only occurs when the browser and server are restarted simultaneously (e.g. start of a work day). A simple page reload recovers the session, so many users never notice or attribute it to a one-off glitch.
  • expire_after on the session store also masks the issue because the session cookie survives browser restart, bypassing the rememberable path entirely.