flippercloud/flipper · error · RuntimeError

Flipper::Middleware::Memoizer no longer initializes with a…

Error message

Flipper::Middleware::Memoizer no longer initializes with a flipper instance or block. Read more at: https://git.io/vSo31.

What it means

Flipper 0.7 removed building the Memoizer middleware around a specific instance: initialize now takes only a Hash of options (:preload, :if, :unless, :env_key) and raises immediately when the second argument is a Flipper::DSL instance or a Proc (lib/flipper/middleware/memoizer.rb:31-39). The instance to memoize must come from the Rack env (set by Flipper::Middleware::SetupEnv) or from Flipper's configured default via Flipper.configure. The guard fails fast at boot instead of silently ignoring the old argument.

Solutions

  1. Move the instance into configuration and mount the memoizer with Hash options only: Flipper.configure { |config| config.default { Flipper.new(adapter) } } then use Flipper::Middleware::Memoizer, preload: true.
  2. If other middleware needs the instance in env, insert Flipper::Middleware::SetupEnv (which still accepts an instance or block) in front of the Memoizer.
  3. Remove the instance/block argument entirely — env_key defaults to 'flipper' and the memoizer falls back to the configured default instance.

Example fix

# before (pre-0.7 API)
use Flipper::Middleware::Memoizer, Flipper.new(redis_adapter)

# after
Flipper.configure do |config|
  config.default { Flipper.new(redis_adapter) }
end
use Flipper::Middleware::Memoizer, preload: true
Defensive patterns

Strategy: validation

Validate before calling

opts = { preload: true }
raise ArgumentError, 'Flipper::Middleware::Memoizer takes a Hash of options only' unless opts.is_a?(Hash)
use Flipper::Middleware::Memoizer, opts

Type guard

def memoizer_opts?(arg)
  arg.is_a?(Hash)
end

Prevention

When it happens

Trigger: Building a Rack/Rails stack with use Flipper::Middleware::Memoizer, Flipper.new(adapter), or passing a lambda/block as the second argument (use Flipper::Middleware::Memoizer, -> { Flipper.new(adapter) }) — initialize sees a Flipper::DSL or Proc in opts and raises while the middleware stack is constructed, before any request is served.

Common situations: Upgrading an app from flipper pre-0.7 to anything newer; copy-pasting middleware snippets from old blog posts, StackOverflow answers, or the pre-0.7 README; initializers that lazily built the flipper instance with a block.

Related errors


AI-assisted analysis of flippercloud/flipper@1f86de3ec9 (2026-08-23). Data as JSON: /api/errors/fe6d00e895255053. Report an issue: GitHub.

Appendix: source

Thrown at lib/flipper/middleware/memoizer.rb:33

      #   use Flipper::Middleware::Memoizer
      #
      #   # using with preload_all features
      #   use Flipper::Middleware::Memoizer, preload: true
      #
      #   # using with preload specific features
      #   use Flipper::Middleware::Memoizer, preload: [:stats, :search, :some_feature]
      #
      #   # using with preload block that returns true/false
      #   use Flipper::Middleware::Memoizer, preload: ->(request) { !request.path.start_with?('/assets') }
      #
      #   # using with preload block that returns specific features
      #   use Flipper::Middleware::Memoizer, preload: ->(request) {
      #     request.path.starts_with?('/admin') ? [:stats, :search] : false
      #   }
      #
      def initialize(app, opts = {})
        if opts.is_a?(Flipper::DSL) || opts.is_a?(Proc)
          raise 'Flipper::Middleware::Memoizer no longer initializes with a flipper instance or block. Read more at: https://git.io/vSo31.'
        end

        @app = app
        @opts = opts
        @env_key = opts.fetch(:env_key, 'flipper')
      end

      def call(env)
        request = Rack::Request.new(env)

        if memoize?(request)
          memoized_call(request)
        else
          @app.call(env)
        end
      end

      private

View on GitHub (pinned to 1f86de3ec9)