CanCanCommunity/cancancan · error · ArgumentError

accessible_by_strategy must be one of #{valid_accessible_by_

Error message

accessible_by_strategy must be one of #{valid_accessible_by_strategies.join(', ')}

What it means

CanCan.accessible_by_strategy= validates the value via validate_accessible_by_strategy! (lib/cancan/config.rb:94) against CanCan.valid_accessible_by_strategies, which is [:left_join] plus the subquery-family strategies (:joined_alias_exists_subquery, :joined_alias_each_rule_as_exists_subquery, :subquery) only when ActiveRecord >= 5 is available. Anything else, including valid-looking values on an old Rails, raises ArgumentError.

Source

Thrown at lib/cancan/config.rb:94

  def self.with_accessible_by_strategy(value)
    return yield if value == accessible_by_strategy

    validate_accessible_by_strategy!(value)

    begin
      strategy_was = accessible_by_strategy
      @accessible_by_strategy = value
      yield
    ensure
      @accessible_by_strategy = strategy_was
    end
  end

  def self.validate_accessible_by_strategy!(value)
    return if valid_accessible_by_strategies.include?(value)

    raise ArgumentError, "accessible_by_strategy must be one of #{valid_accessible_by_strategies.join(', ')}"
  end

  def self.does_not_support_subquery_strategy?
    !defined?(CanCan::ModelAdapters::ActiveRecordAdapter) ||
      CanCan::ModelAdapters::ActiveRecordAdapter.version_lower?('5.0.0')
  end
end

View on GitHub (pinned to 8c1bf153a3)

Solutions

  1. Use a value from the allowed list: check it live with puts CanCan.valid_accessible_by_strategies.
  2. On Rails < 5, use only :left_join.
  3. Derive the value defensively: CanCan.accessible_by_strategy = (ENV['STRATEGY'] || :left_join).to_sym, after confirming membership in the valid list.

Example fix

# before
CanCan.accessible_by_strategy = ENV.fetch('CANCAN_STRATEGY', :left_join)  # 'subquerry' from ENV -> ArgumentError

# after
strategy = ENV.fetch('CANCAN_STRATEGY', :left_join).to_sym
CanCan.accessible_by_strategy = strategy if CanCan.valid_accessible_by_strategies.include?(strategy)
Defensive patterns

Strategy: validation

Validate before calling

strategy = ENV.fetch('CANCAN_STRATEGY', :left_join).to_sym
raise ArgumentError, "invalid strategy #{strategy}; valid: #{CanCan.valid_accessible_by_strategies.join(', ')}" unless CanCan.valid_accessible_by_strategies.include?(strategy)
CanCan.accessible_by_strategy = strategy

Type guard

def valid_strategy?(value)
  CanCan.valid_accessible_by_strategies.include?(value.to_s.to_sym)
end

Try / catch

begin
  CanCan.accessible_by_strategy = strategy
rescue ArgumentError => e
  raise ConfigError, e.message
end

Prevention

When it happens

Trigger: Typo'd or wrong-type values: CanCan.accessible_by_strategy = :subquerry, 'subquery' (String), or :leftJoin; setting :subquery when ActiveRecord is < 5 so it is not in the valid list; passing an ad-hoc strategy to CanCan.with_accessible_by_strategy in a spec.

Common situations: Initializers drifted from a README snippet whose supported values differ across cancancan versions; environment divergence where development is on Rails 7 but a staging app pins Rails 4; string vs symbol mismatch when reading the value from ENV.

Related errors


AI-assisted analysis of CanCanCommunity/cancancan@8c1bf153a3 (2026-08-21). Data as JSON: /api/errors/83973676849e4678. Report an issue: GitHub.