flippercloud/flipper · error · RuntimeError

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

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.

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)

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.