puppetlabs/puppet · error · ArgumentError

Parameters cannot be added after a block parameter

Error message

Parameters cannot be added after a block parameter

What it means

internal_param is the shared body behind param, optional_param, and the repeated forms. It rejects any parameter declared after a block parameter (@block_type set), because positional parameters bind before the trailing block in a Puppet dispatch. The error surfaces as ArgumentError at definition time.

Source

Thrown at lib/puppet/functions.rb:535

    end

    # Defines the return type. Defaults to 'Any'
    # @param [String] type a reference to a Puppet Data Type
    #
    # @api public
    def return_type(type)
      unless type.is_a?(String) || type.is_a?(Puppet::Pops::Types::PAnyType)
        raise ArgumentError, _("Argument to 'return_type' must be a String reference to a Puppet Data Type. Got %{type_class}") % { type_class: type.class }
      end

      @return_type = type
    end

    private

    # @api private
    def internal_param(type, name, repeat = false)
      raise ArgumentError, _('Parameters cannot be added after a block parameter') unless @block_type.nil?
      raise ArgumentError, _('Parameters cannot be added after a repeated parameter') if @max == :default

      if name.is_a?(String)
        raise ArgumentError, _("Parameter name argument must be a Symbol. Got %{name_class}") % { name_class: name.class }
      end

      if type.is_a?(String) || type.is_a?(Puppet::Pops::Types::PAnyType)
        @types << type
        @names << name
        # mark what should be picked for this position when dispatching
        if repeat
          @weaving << -@names.size()
        else
          @weaving << @names.size() - 1
        end
      else
        raise ArgumentError, _("Parameter 'type' must be a String reference to a Puppet Data Type. Got %{type_class}") % { type_class: type.class }
      end

View on GitHub (pinned to e227c27540)

Solutions

  1. Move all positional param/optional_param declarations above the block_param line.
  2. Treat block_param and optional_block_param as the last declaration in every dispatch block, always.
  3. If a linter is available, enforce that ordering rule on function files.

Example fix

# before
 dispatch :m do
   block_param 'Callable', :block
   param 'String', :x        # raises: parameter after block
 end

# after: block parameter goes last
 dispatch :m do
   param 'String', :x
   block_param 'Callable', :block
 end
Defensive patterns

Strategy: validation

Validate before calling

# CI grep: a param-style declaration after block_param in one dispatch block
! grep -Pzo 'dispatch[^}]*block_param[^}]*\n[^}]*\s(param|optional_param|required_repeated_param|optional_repeated_param) ' lib/puppet/functions/**/*.rb

Prevention

When it happens

Trigger: dispatch :m do block_param 'Callable', :block; param 'String', :x end. The param line after the block_param line raises immediately.

Common situations: Appending a new argument to an existing signature at the bottom of the block, under an existing block_param; reordering lines during cleanup.

Related errors


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