CanCanCommunity/cancancan · error · CanCan::Error
Subject is required for #{action}
Error message
Subject is required for #{action} What it means
Rule#initialize (lib/cancan/rule.rb:28) requires a subject whenever an action is given: raise Error, "Subject is required for #{action}" if action && subject.nil?. The only subject-less form allowed is the fully bare can/cannot (action and subject both nil), which becomes a match-all rule; an action without a subject is almost always a truncated can call or a nil variable.
Source
Thrown at lib/cancan/rule.rb:28
# helpful methods to determine permission checking and conditions hash generation.
class Rule # :nodoc:
include ConditionsMatcher
include Relevant
include ParameterValidators
attr_reader :base_behavior, :subjects, :actions, :conditions, :attributes, :block
attr_writer :expanded_actions, :conditions
# The first argument when initializing is the base_behavior which is a true/false
# value. True for "can" and false for "cannot". The next two arguments are the action
# and subject respectively (such as :read, @project). The third argument is a hash
# of conditions and the last one is the block passed to the "can" call.
def initialize(base_behavior, action, subject, *extra_args, &block)
# for backwards compatibility, attributes are an optional parameter. Check if
# attributes were passed or are actually conditions
attributes, extra_args = parse_attributes_from_extra_args(extra_args)
condition_and_block_check(extra_args, block, action, subject)
@match_all = action.nil? && subject.nil?
raise Error, "Subject is required for #{action}" if action && subject.nil?
@base_behavior = base_behavior
@actions = wrap(action)
@subjects = wrap(subject)
@attributes = wrap(attributes)
@conditions = extra_args || {}
@block = block
end
def inspect
repr = "#<#{self.class.name}"
repr += "#{@base_behavior ? 'can' : 'cannot'} #{@actions.inspect}, #{@subjects.inspect}, #{@attributes.inspect}"
if with_scope?
repr += ", #{@conditions.where_values_hash}"
elsif [Hash, String].include?(@conditions.class)
repr += ", #{@conditions.inspect}"
endView on GitHub (pinned to 8c1bf153a3)
Solutions
- Add the subject: can :read, Article, or for everything can :read, :all.
- For non-model pages use a symbol namespace: can :read, :dashboard.
- Guard nil subjects before defining rules: only define the rule when the subject variable is present.
Example fix
# before can :read # CanCan::Error: Subject is required for read can :read, maybe_project # maybe_project nil at definition time # after can :read, :all can :read, Project if maybe_project # or restructure so the subject is never nil
Defensive patterns
Strategy: validation
Validate before calling
# central guarded definition helper in the Ability
def define_ability(action, subject = nil, **conditions, &block)
raise ArgumentError, "Subject is required for #{action}" if action && subject.nil?
can(action, subject || :all, **conditions, &block)
end Type guard
def complete_rule?(action, subject) action.nil? || !subject.nil? end
Try / catch
begin
can :read, subject_var
rescue CanCan::Error => e
Rails.logger.error("bad ability definition: #{e.message}")
raise # definition bugs must surface at boot, not be swallowed
end Prevention
- Always write both arguments: can :read, Article (use :all when you mean everything).
- Never build rules from variables that can be nil; guard with if subject first.
- Instantiate the Ability once in a boot check or spec so definition errors fail fast at startup.
- Run rubocop rules or a custom cop forbidding bare can/:cannot calls with a single argument.
When it happens
Trigger: can :read with no second argument; cannot :delete; a subject variable that evaluates to nil at rule-definition time (can :read, @project inside an ability built before @project exists); passing nil explicitly via can :read, nil.
Common situations: Copy-paste truncation of an ability line; abilities built with variables that can be nil (conditional subjects); refactoring that renames a variable to nil in some branch.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- You can't specify target (#{target}) as alias because it is
- A hash of conditions is mutually exclusive with a block. Che
- You are not authorized to access this page.
- The can? and cannot? call cannot be used with a raw sql 'can
- accessible_by_strategy = :subquery requires ActiveRecord 5 o
AI-assisted analysis of CanCanCommunity/cancancan@8c1bf153a3 (2026-08-21).
Data as JSON: /api/errors/c7f827ec6e463cf2.
Report an issue: GitHub.