puppetlabs/puppet · error · ArgumentError

The argument 'puppet_code' must be a String, got %{type}

Error message

The argument 'puppet_code' must be a String, got %{type}

What it means

PAL's Compiler#evaluate_string evaluates a snippet of Puppet language code in top scope. nil and '' short-circuit to nil, but any other non-String value (Symbol, Integer, Array, Hash) raises ArgumentError naming the actual class. The check exists so the failure happens at the API boundary instead of deep inside the parser with a confusing message.

Source

Thrown at lib/puppet/pal/compiler.rb:89

    end

    # Evaluates a string of puppet language code in top scope.
    # A "source_file" reference to a source can be given - if not an actual file name, by convention the name should
    # be bracketed with < > to indicate it is something symbolic; for example `<commandline>` if the string was given on the
    # command line.
    #
    # If the given `puppet_code` is `nil` or an empty string, `nil` is returned, otherwise the result of evaluating the
    # puppet language string. The given string must form a complete and valid expression/statement as an error is raised
    # otherwise. That is, it is not possible to divide a compound expression by line and evaluate each line individually.
    #
    # @param puppet_code [String, nil] the puppet language code to evaluate, must be a complete expression/statement
    # @param source_file [String, nil] an optional reference to a source (a file or symbolic name/location)
    # @return [Object] what the `puppet_code` evaluates to
    #
    def evaluate_string(puppet_code, source_file = nil)
      return nil if puppet_code.nil? || puppet_code == ''
      unless puppet_code.is_a?(String)
        raise ArgumentError, _("The argument 'puppet_code' must be a String, got %{type}") % { type: puppet_code.class }
      end

      evaluate(parse_string(puppet_code, source_file))
    end

    # Evaluates a puppet language file in top scope.
    # The file must exist and contain valid puppet language code or an error is raised.
    #
    # @param file [Path, String] an absolute path to a file with puppet language code, must exist
    # @return [Object] what the last evaluated expression in the file evaluated to
    #
    def evaluate_file(file)
      evaluate(parse_file(file))
    end

    # Evaluates an AST obtained from `parse_string` or `parse_file` in topscope.
    # If the ast is a `Puppet::Pops::Model::Program` (what is returned from the `parse` methods, any definitions
    # in the program (that is, any function, plan, etc. that is defined will be made available for use).

View on GitHub (pinned to e227c27540)

Solutions

  1. Coerce before calling: evaluate_string(puppet_code.to_s)
  2. Fix the producer so the value really is the Puppet source string
  3. Skip the call for nil/empty (already supported) and raise your own descriptive error for other types

Example fix

# before: Symbol passed instead of source text
compiler.evaluate_string(options[:snippet])   # :include_foo

# after
compiler.evaluate_string(options[:snippet].to_s)
Defensive patterns

Strategy: type-guard

Type guard

def puppet_code?(value)
  value.is_a?(String)
end

raise ArgumentError, 'puppet_code must be a String' unless puppet_code?(code)

Prevention

When it happens

Trigger: evaluate_string(:'include foo') (a Symbol from keyword-style code), evaluate_string(42), or passing a variable that was never converted to source text, such as an options-hash value fetched with a typo'd key or a nested structure from YAML instead of the snippet string.

Common situations: Rake tasks and rspec-puppet-style helpers that build PAL calls dynamically from config; data-driven tooling where the snippet comes from YAML and is accidentally a list of lines or a symbol.

Related errors


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