puppetlabs/puppet · error · ArgumentError
before action hook for %{name} is a %{class_name}, not a pro
Error message
before action hook for %{name} is a %{class_name}, not a proc What it means
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.
Source
Thrown at lib/puppet/interface/option.rb:158
@default and @default.call
end
attr_reader :parent, :name, :aliases, :optparse, :required
def required=(value)
if has_default?
raise ArgumentError, _("%{name} can't be optional and have a default value") % { name: self }
end
@required = value
end
attr_reader :before_action
def before_action=(proc)
unless proc.is_a? Proc
# TRANSLATORS 'proc' is a Ruby block of code
raise ArgumentError, _("before action hook for %{name} is a %{class_name}, not a proc") %
{ name: self, class_name: proc.class.name.inspect }
end
@before_action =
@parent.__send__(:__add_method, __decoration_name(:before), proc)
end
attr_reader :after_action
def after_action=(proc)
unless proc.is_a? Proc
# TRANSLATORS 'proc' is a Ruby block of code
raise ArgumentError, _("after action hook for %{name} is a %{class_name}, not a proc") %
{ name: self, class_name: proc.class.name.inspect }
end
@after_action =
@parent.__send__(:__add_method, __decoration_name(:after), proc)
end
View on GitHub (pinned to e227c27540)
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
Example fix
# before
opt.before_action = :validate
# after
opt.before_action = proc { |action, args, options| validate(options) } Defensive patterns
Strategy: type-guard
Type guard
def hook!(value, what)
raise ArgumentError, "#{what} must be a Proc" unless value.is_a?(Proc)
value
end
opt.before_action = hook!(candidate, 'before_action') Prevention
- 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
When it happens
Trigger: `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.
Common situations: Refactoring DSL blocks into named methods; configuration-driven hook registration that records names instead of blocks.
Related errors
- default value for %{name} is a %{class_name}, not a proc
- after action hook for %{name} is a %{class_name}, not a proc
- %{name} can't be optional and have a default value
- %{option} before_action requires a block
- %{option} already has a before_action set
AI-assisted analysis of puppetlabs/puppet@e227c27540 (2026-08-21).
Data as JSON: /api/errors/5877af9d45b390e4.
Report an issue: GitHub.