{"record":{"id":"5877af9d45b390e4","repo":"puppetlabs/puppet","slug":"before-action-hook-for-name-is-a-class-name","errorCode":null,"errorMessage":"before action hook for %{name} is a %{class_name}, not a proc","messagePattern":"before action hook for %(.+?) is a %(.+?), not a proc","errorType":"exception","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"lib/puppet/interface/option.rb","lineNumber":158,"sourceCode":"    @default and @default.call\n  end\n\n  attr_reader :parent, :name, :aliases, :optparse, :required\n\n  def required=(value)\n    if has_default?\n      raise ArgumentError, _(\"%{name} can't be optional and have a default value\") % { name: self }\n    end\n\n    @required = value\n  end\n\n  attr_reader :before_action\n\n  def before_action=(proc)\n    unless proc.is_a? Proc\n      # TRANSLATORS 'proc' is a Ruby block of code\n      raise ArgumentError, _(\"before action hook for %{name} is a %{class_name}, not a proc\") %\n                           { name: self, class_name: proc.class.name.inspect }\n    end\n    @before_action =\n      @parent.__send__(:__add_method, __decoration_name(:before), proc)\n  end\n\n  attr_reader :after_action\n\n  def after_action=(proc)\n    unless proc.is_a? Proc\n      # TRANSLATORS 'proc' is a Ruby block of code\n      raise ArgumentError, _(\"after action hook for %{name} is a %{class_name}, not a proc\") %\n                           { name: self, class_name: proc.class.name.inspect }\n    end\n    @after_action =\n      @parent.__send__(:__add_method, __decoration_name(:after), proc)\n  end\n","sourceCodeStart":140,"sourceCodeEnd":176,"githubUrl":"https://github.com/puppetlabs/puppet/blob/e227c27540975c25aa22d533a52424a9d2fc886a/lib/puppet/interface/option.rb#L140-L176","documentation":"Puppet::Interface::Option#before_action= registers a validation hook by sending `__add_method` to the parent face/action and refuses anything that is not a Proc (lib/puppet/interface/option.rb:158). The hook is invoked as `call(action, args, options)` when the action runs, so a Symbol or Method would never execute and fail silently. The DSL `before_action { |action, args, options| ... }` always supplies a proper block.","triggerScenarios":"`opt.before_action = :validate` (Symbol); `opt.before_action = method(:validate)` (Method is not a Proc); storing hook names from a config hash and assigning them directly.","commonSituations":"Refactoring DSL blocks into named methods; configuration-driven hook registration that records names instead of blocks.","solutions":["Pass a wrapping proc: `opt.before_action = proc { |action, args, options| validate(action, args, options) }`","Convert Method objects with `.to_proc` (Ruby 2.7+) — the result is a real Proc","Prefer the DSL `before_action` inside the option block"],"exampleFix":"# before\nopt.before_action = :validate\n\n# after\nopt.before_action = proc { |action, args, options| validate(options) }","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"def hook!(value, what)\n  raise ArgumentError, \"#{what} must be a Proc\" unless value.is_a?(Proc)\n  value\nend\n\nopt.before_action = hook!(candidate, 'before_action')","tryCatchPattern":null,"preventionTips":["Register hooks with the DSL `before_action { |action, args, options| ... }`","Wrap named methods in a proc; convert Method objects with `.to_proc`","Keep hook storage as Procs, not Symbols, in any config-driven face machinery"],"tags":["puppet","faces","dsl","proc","argumenterror"],"backgroundTag":"wrong-argument-type","analyzedSha":"e227c27540975c25aa22d533a52424a9d2fc886a","analyzedAt":"2026-08-21T20:49:46.650Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}