{"record":{"id":"372675f69c291adc","repo":"puppetlabs/puppet","slug":"option-before-action-requires-a-block","errorCode":null,"errorMessage":"%{option} before_action requires a block","messagePattern":"%(.+?) before_action requires a block","errorType":"exception","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"lib/puppet/interface/option_builder.rb","lineNumber":47,"sourceCode":"    unless private_method_defined? dsl\n      define_method(dsl) do |value| @option.send(setter, value) end\n    end\n  end\n\n  # Override some methods that deal in blocks, not objects.\n\n  # Sets a block to be executed when an action is invoked before the\n  # 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)","sourceCodeStart":29,"sourceCodeEnd":65,"githubUrl":"https://github.com/puppetlabs/puppet/blob/e227c27540975c25aa22d533a52424a9d2fc886a/lib/puppet/interface/option_builder.rb#L29-L65","documentation":"Puppet::Interface::OptionBuilder#before_action, used inside `option ... do ... end` blocks in the Faces DSL, requires a block literal (lib/puppet/interface/option_builder.rb:47). Calling it with no block — a bare `before_action` — raises ArgumentError at face-load time. `%{option}` renders the Option being built, i.e. its dashed name such as --environment.","triggerScenarios":"`option '--foo' do before_action end` (no block); `before_action(&hook)` where hook is nil; intending to call a helper method literally named before_action.","commonSituations":"Refactoring a block body into a method and leaving a bare call; passing an optional hook variable that was never set; misunderstanding the DSL as method-reference style.","solutions":["Always pass a literal block: `before_action { |action, args, options| ... }`","To reuse a named method, wrap it: `before_action { |*a| my_validator(*a) }`","If the hook is conditional, guard the whole call: `before_action { ... } if hook_needed`"],"exampleFix":"# before\noption \"--verbose\" do\n  before_action\nend\n\n# after\noption \"--verbose\" do\n  before_action do |action, args, options|\n    raise \"--verbose not supported here\" if options[:verbose]\n  end\nend","handlingStrategy":"validation","validationCode":"# when the hook comes from a variable\nraise ArgumentError, 'before_action needs a block' if hook.nil?\nbefore_action(&hook) # inside the option block","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always write `before_action do |action, args, options| ... end` with a literal block","Check hook variables for nil before passing them with `&`","Name helper methods differently from DSL methods to avoid bare-call mistakes"],"tags":["puppet","faces","dsl","block","argumenterror"],"backgroundTag":"missing-block-argument","analyzedSha":"e227c27540975c25aa22d533a52424a9d2fc886a","analyzedAt":"2026-08-21T20:49:46.650Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}