puppetlabs/puppet · error · ArgumentError

Parameters cannot be added after a repeated parameter

Error message

Parameters cannot be added after a repeated parameter

What it means

A repeated parameter sets @max to :default, marking the signature as variadic. internal_param rejects any later parameter declaration in that state, because nothing can bind after a 1..N capture. The repeated parameter must be last, or immediately before a block parameter.

Source

Thrown at lib/puppet/functions.rb:536

    # 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
    end

View on GitHub (pinned to e227c27540)

Solutions

  1. Move the fixed parameter above the repeated one.
  2. If the trailing parameter is optional in practice, fold it into the repeated capture and default it inside the method body.
  3. Remember the legal tail order: required params, optional params, repeated param, block param.

Example fix

# before
 dispatch :m do
   required_repeated_param 'String', :rest
   param 'String', :last      # raises: parameter after repeated
 end

# after: repeated parameter goes last (before any block)
 dispatch :m do
   param 'String', :last
   required_repeated_param 'String', :rest
 end
Defensive patterns

Strategy: validation

Validate before calling

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

Prevention

When it happens

Trigger: dispatch :m do required_repeated_param 'String', :rest; param 'String', :last end. The param line after the repeated line raises at definition time.

Common situations: Adding a trailing argument to a signature that already ends with a variadic capture; converting the last positional into a splat and forgetting to move earlier declarations.

Related errors


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