flippercloud/flipper · error · Flipper::Adapters::ActorLimit::LimitExceeded

Actor limit of #{@limit} exceeded for feature #{feature.key}

Error message

Actor limit of #{@limit} exceeded for feature #{feature.key}. See https://www.flippercloud.io/docs/features/actors#limitations

What it means

The ActorLimit adapter wrapper (used by Flipper Cloud) caps how many individual actors may be enabled per feature (default limit 100). Its enable() raises ActorLimit::LimitExceeded when you enable an actor on a feature whose actors_value set already has at least `limit` entries, because per-actor gate rows do not scale and gate reads get slow. The check is skipped for non-actor gates and inside ActorLimit.with_sync_mode, which the sync machinery uses to mirror remote state.

Source

Thrown at lib/flipper/adapters/actor_limit.rb:41

        # Executes a block with sync mode enabled. Actor limits will
        # not be enforced within the block.
        def with_sync_mode
          old_value = sync_mode
          self.sync_mode = true
          yield
        ensure
          self.sync_mode = old_value
        end
      end

      def initialize(adapter, limit = 100)
        super(adapter)
        @limit = limit
      end

      def enable(feature, gate, resource)
        if gate.is_a?(Flipper::Gates::Actor) && !self.class.sync_mode && over_limit?(feature)
          raise LimitExceeded, "Actor limit of #{@limit} exceeded for feature #{feature.key}. See https://www.flippercloud.io/docs/features/actors#limitations"
        else
          super
        end
      end

      private

      def over_limit?(feature)
        feature.actors_value.size >= @limit
      end
    end
  end
end

View on GitHub (pinned to 1f86de3ec9)

Solutions

  1. Switch to a rollout mechanism that scales: feature.enable_percentage_of_actors(25), enable_group, or enable_expression.
  2. Prune the list first: disable actors you no longer need (feature.disable_actor(actor)) so the count drops below the limit before enabling more.
  3. If you are deliberately syncing state (e.g. replicating a remote set), wrap the writes in Flipper::Adapters::ActorLimit.with_sync_mode { ... } to bypass the check.
  4. If you constructed Flipper::Adapters::ActorLimit yourself with a custom limit, review whether that limit fits the feature's usage before raising it.

Example fix

# before
users.find_each { |user| Flipper[:beta].enable_actor user } # raises at actor #101

# after
Flipper[:beta].enable_percentage_of_actors 25
# or target a stable cohort
Flipper.register(:beta_optins) { |actor| actor.respond_to?(:beta_optin?) && actor.beta_optin? }
Flipper[:beta].enable_group :beta_optins
Defensive patterns

Strategy: validation

Validate before calling

def enable_actor_safely(feature, actor, limit = 100)
  if feature.actors_value.size >= limit
    feature.enable_percentage_of_actors(100) # or another rollout strategy
  else
    feature.enable_actor(actor)
  end
end

Try / catch

begin
  Flipper[:beta].enable_actor(user)
rescue Flipper::Adapters::ActorLimit::LimitExceeded
  Flipper[:beta].enable_percentage_of_actors(25) # fall back to a scalable rollout
end

Prevention

When it happens

Trigger: feature.enable_actor(user) / Flipper.enable(:beta, user) on a feature that already has >= limit (default 100) enabled actors, outside of sync mode. Typically reached in a loop that enables users one by one.

Common situations: Progressive individual rollouts where a script keeps calling enable_actor past 100 users; backfills/imports that enable lists of actors; teams hitting the Flipper Cloud per-feature actor cap; code migrated from boolean flags to individual actor enables instead of percentage rollouts.

Related errors


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