{"record":{"id":"c7f827ec6e463cf2","repo":"CanCanCommunity/cancancan","slug":"subject-is-required-for-action","errorCode":null,"errorMessage":"Subject is required for #{action}","messagePattern":"Subject is required for #(.+?)","errorType":"exception","errorClass":"CanCan::Error","httpStatus":null,"severity":"error","filePath":"lib/cancan/rule.rb","lineNumber":28,"sourceCode":"  # helpful methods to determine permission checking and conditions hash generation.\n  class Rule # :nodoc:\n    include ConditionsMatcher\n    include Relevant\n    include ParameterValidators\n    attr_reader :base_behavior, :subjects, :actions, :conditions, :attributes, :block\n    attr_writer :expanded_actions, :conditions\n\n    # The first argument when initializing is the base_behavior which is a true/false\n    # value. True for \"can\" and false for \"cannot\". The next two arguments are the action\n    # and subject respectively (such as :read, @project). The third argument is a hash\n    # of conditions and the last one is the block passed to the \"can\" call.\n    def initialize(base_behavior, action, subject, *extra_args, &block)\n      # for backwards compatibility, attributes are an optional parameter. Check if\n      # attributes were passed or are actually conditions\n      attributes, extra_args = parse_attributes_from_extra_args(extra_args)\n      condition_and_block_check(extra_args, block, action, subject)\n      @match_all = action.nil? && subject.nil?\n      raise Error, \"Subject is required for #{action}\" if action && subject.nil?\n\n      @base_behavior = base_behavior\n      @actions = wrap(action)\n      @subjects = wrap(subject)\n      @attributes = wrap(attributes)\n      @conditions = extra_args || {}\n      @block = block\n    end\n\n    def inspect\n      repr = \"#<#{self.class.name}\"\n      repr += \"#{@base_behavior ? 'can' : 'cannot'} #{@actions.inspect}, #{@subjects.inspect}, #{@attributes.inspect}\"\n\n      if with_scope?\n        repr += \", #{@conditions.where_values_hash}\"\n      elsif [Hash, String].include?(@conditions.class)\n        repr += \", #{@conditions.inspect}\"\n      end","sourceCodeStart":10,"sourceCodeEnd":46,"githubUrl":"https://github.com/CanCanCommunity/cancancan/blob/8c1bf153a3da7b2261d6fa4a5f84eb28e2feb828/lib/cancan/rule.rb#L10-L46","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"# before\ncan :read                # CanCan::Error: Subject is required for read\ncan :read, maybe_project # maybe_project nil at definition time\n\n# after\ncan :read, :all\ncan :read, Project if maybe_project  # or restructure so the subject is never nil","handlingStrategy":"validation","validationCode":"# central guarded definition helper in the Ability\ndef define_ability(action, subject = nil, **conditions, &block)\n  raise ArgumentError, \"Subject is required for #{action}\" if action && subject.nil?\n  can(action, subject || :all, **conditions, &block)\nend","typeGuard":"def complete_rule?(action, subject)\n  action.nil? || !subject.nil?\nend","tryCatchPattern":"begin\n  can :read, subject_var\nrescue CanCan::Error => e\n  Rails.logger.error(\"bad ability definition: #{e.message}\")\n  raise # definition bugs must surface at boot, not be swallowed\nend","preventionTips":["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."],"tags":["rule-definition","missing-argument","cancancan","ruby"],"backgroundTag":"missing-required-argument","analyzedSha":"8c1bf153a3da7b2261d6fa4a5f84eb28e2feb828","analyzedAt":"2026-08-21T20:05:55.000Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}