{"record":{"id":"4f0851ab91e9357b","repo":"puppetlabs/puppet","slug":"before-action-takes-three-arguments-action-args","errorCode":null,"errorMessage":"before_action takes three arguments, action, args, and options","messagePattern":"before_action takes three arguments, action, args, and options","errorType":"exception","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"lib/puppet/interface/option_builder.rb","lineNumber":55,"sourceCode":"  # main action code. This is most commonly used to validate an option.\n  # @yieldparam action [Puppet::Interface::Action] The action being\n  #   invoked\n  # @yieldparam args [Array] The arguments given to the action\n  # @yieldparam options [Hash<Symbol=>Object>] Any options set\n  # @api public\n  # @dsl Faces\n  def before_action(&block)\n    unless block\n      # TRANSLATORS 'before_action' is a method name and should not be translated\n      raise ArgumentError, _(\"%{option} before_action requires a block\") % { option: @option }\n    end\n    if @option.before_action\n      # TRANSLATORS 'before_action' is a method name and should not be translated\n      raise ArgumentError, _(\"%{option} already has a before_action set\") % { option: @option }\n    end\n    unless block.arity == 3 then\n      # TRANSLATORS 'before_action' is a method name and should not be translated\n      raise ArgumentError, _(\"before_action takes three arguments, action, args, and options\")\n    end\n\n    @option.before_action = block\n  end\n\n  # Sets a block to be executed after an action is invoked.\n  # !(see before_action)\n  # @api public\n  # @dsl Faces\n  def after_action(&block)\n    unless block\n      # TRANSLATORS 'after_action' is a method name and should not be translated\n      raise ArgumentError, _(\"%{option} after_action requires a block\") % { option: @option }\n    end\n    if @option.after_action\n      # TRANSLATORS 'after_action' is a method name and should not be translated\n      raise ArgumentError, _(\"%{option} already has an after_action set\") % { option: @option }\n    end","sourceCodeStart":37,"sourceCodeEnd":73,"githubUrl":"https://github.com/puppetlabs/puppet/blob/e227c27540975c25aa22d533a52424a9d2fc886a/lib/puppet/interface/option_builder.rb#L37-L73","documentation":"OptionBuilder#before_action invokes the hook as `call(action, args, options)` and therefore enforces `block.arity == 3` (lib/puppet/interface/option_builder.rb:55). Blocks with fewer (or more) declared parameters fail, as do splat blocks like `{ |*a| }` whose arity is negative. Declare exactly three parameters.","triggerScenarios":"`before_action { |action, args| ... }` (arity 2); `before_action { |*a| ... }` (arity -1); a proc with any non-exact signature that does not evaluate to 3.","commonSituations":"Refactoring a hook down to two params; copying a 2-arg hook from another framework; 'catch-all' splat style blocks.","solutions":["Declare all three parameters: `before_action { |action, args, options| ... }`","If you only need one value, accept three and underscore the unused: `|_action, _args, options|`","When constructing the hook as an object, assert `hook.arity == 3` before passing it with `&hook`"],"exampleFix":"# before\nbefore_action { |action, args| validate(args) }\n\n# after\nbefore_action { |action, args, options| validate(args) }","handlingStrategy":"validation","validationCode":"hook = proc { |action, args, options| validate(args) }\nraise ArgumentError, 'before_action hook must take exactly 3 args' unless hook.arity == 3\nbefore_action(&hook)","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Standardize on `|action, args, options|` (underscoring unused ones) for every action hook","Avoid splat blocks (`|*a|`) for hooks — their arity is negative and always rejected","Unit-test DSL option blocks so arity mistakes surface before face load"],"tags":["puppet","faces","dsl","arity","argumenterror"],"backgroundTag":"block-arity-mismatch","analyzedSha":"e227c27540975c25aa22d533a52424a9d2fc886a","analyzedAt":"2026-08-21T20:49:46.650Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}