puppetlabs/puppet · error · ArgumentError

after action hook for %{name} is a %{class_name}, not a proc

Error message

after action hook for %{name} is a %{class_name}, not a proc

What it means

Puppet::Interface::Option#after_action= registers a post-action hook the same way before_action does and equally requires a Proc (lib/puppet/interface/option.rb:170). Anything non-callable (Symbol, Method, String) is rejected because the hook is later invoked with `call`. Use the DSL `after_action { |action, args, options| ... }` to get the block handling for free.

Source

Thrown at lib/puppet/interface/option.rb:170

  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

  def __decoration_name(type)
    if @parent.is_a? Puppet::Interface::Action then
      :"option #{name} from #{parent.name} #{type} decoration"
    else
      :"option #{name} #{type} decoration"
    end
  end
end

View on GitHub (pinned to e227c27540)

Solutions

  1. Pass a wrapping proc: `opt.after_action = proc { |action, args, options| log_result(options) }`
  2. Convert Method objects with `.to_proc`
  3. Prefer the DSL `after_action` inside the option block

Example fix

# before
opt.after_action = :log_result

# after
opt.after_action = proc { |action, args, options| log_result(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.after_action = hook!(candidate, 'after_action')

Prevention

When it happens

Trigger: `opt.after_action = :log_result` (Symbol); `opt.after_action = method(:log_result)` (Method, not a Proc); assigning a hook variable that holds nil or a name string.

Common situations: Adding cleanup/teardown hooks by name; refactoring face code into helper methods and assigning references instead of wrappers.

Related errors


AI-assisted analysis of puppetlabs/puppet@e227c27540 (2026-08-21). Data as JSON: /api/errors/2acc4a756b9366f9. Report an issue: GitHub.