puppetlabs/puppet · error · ArgumentError
before_action takes three arguments, action, args, and optio
Error message
before_action takes three arguments, action, args, and options
What it means
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.
Source
Thrown at lib/puppet/interface/option_builder.rb:55
# main action code. This is most commonly used to validate an option.
# @yieldparam action [Puppet::Interface::Action] The action being
# invoked
# @yieldparam args [Array] The arguments given to the action
# @yieldparam options [Hash<Symbol=>Object>] Any options set
# @api public
# @dsl Faces
def before_action(&block)
unless block
# TRANSLATORS 'before_action' is a method name and should not be translated
raise ArgumentError, _("%{option} before_action requires a block") % { option: @option }
end
if @option.before_action
# TRANSLATORS 'before_action' is a method name and should not be translated
raise ArgumentError, _("%{option} already has a before_action set") % { option: @option }
end
unless block.arity == 3 then
# TRANSLATORS 'before_action' is a method name and should not be translated
raise ArgumentError, _("before_action takes three arguments, action, args, and options")
end
@option.before_action = block
end
# Sets a block to be executed after an action is invoked.
# !(see before_action)
# @api public
# @dsl Faces
def after_action(&block)
unless block
# TRANSLATORS 'after_action' is a method name and should not be translated
raise ArgumentError, _("%{option} after_action requires a block") % { option: @option }
end
if @option.after_action
# TRANSLATORS 'after_action' is a method name and should not be translated
raise ArgumentError, _("%{option} already has an after_action set") % { option: @option }
endView on GitHub (pinned to e227c27540)
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`
Example fix
# before
before_action { |action, args| validate(args) }
# after
before_action { |action, args, options| validate(args) } Defensive patterns
Strategy: validation
Validate before calling
hook = proc { |action, args, options| validate(args) }
raise ArgumentError, 'before_action hook must take exactly 3 args' unless hook.arity == 3
before_action(&hook) Prevention
- 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
When it happens
Trigger: `before_action { |action, args| ... }` (arity 2); `before_action { |*a| ... }` (arity -1); a proc with any non-exact signature that does not evaluate to 3.
Common situations: Refactoring a hook down to two params; copying a 2-arg hook from another framework; 'catch-all' splat style blocks.
Related errors
- after_action takes three arguments, action, args, and option
- %{option} default_to block should not take any arguments
- %{name} can't be optional and have a default value
- default value for %{name} is a %{class_name}, not a proc
- before action hook for %{name} is a %{class_name}, not a pro
AI-assisted analysis of puppetlabs/puppet@e227c27540 (2026-08-21).
Data as JSON: /api/errors/4f0851ab91e9357b.
Report an issue: GitHub.