puppetlabs/puppet · error · ArgumentError
The argument 'file' must be a String, got %{type}
Error message
The argument 'file' must be a String, got %{type} What it means
Compiler#parse_file requires the file argument to be a String path, even though the doc comment mentions Path. Passing a Pathname (very common in Ruby tooling) or an IO object raises ArgumentError naming the actual class. The path is handed straight to the parser, which expects a String.
Source
Thrown at lib/puppet/pal/compiler.rb:158
# @return [Puppet::Pops::Model::Program] returns a `Program` instance on success
#
def parse_string(code_string, source_file = nil)
unless code_string.is_a?(String)
raise ArgumentError, _("The argument 'code_string' must be a String, got %{type}") % { type: code_string.class }
end
internal_evaluator.parse_string(code_string, source_file)
end
# Parses and validates a puppet language file and returns an instance of Puppet::Pops::Model::Program on success.
# If the content is not valid an error is raised.
#
# @param file [String] a file with puppet language content to parse and validate
# @return [Puppet::Pops::Model::Program] returns a `Program` instance on success
#
def parse_file(file)
unless file.is_a?(String)
raise ArgumentError, _("The argument 'file' must be a String, got %{type}") % { type: file.class }
end
internal_evaluator.parse_file(file)
end
# Parses a puppet data type given in String format and returns that type, or raises an error.
# A type is needed in calls to `new` to create an instance of the data type, or to perform type checking
# of values - typically using `type.instance?(obj)` to check if `obj` is an instance of the type.
#
# @example Verify if obj is an instance of a data type
# # evaluates to true
# pal.type('Enum[red, blue]').instance?("blue")
#
# @example Create an instance of a data type
# # using an already create type
# t = pal.type('Car')
# pal.create(t, 'color' => 'black', 'make' => 't-ford')
#View on GitHub (pinned to e227c27540)
Solutions
- Convert explicitly: parse_file(path.to_s)
- Standardize on String paths at the PAL boundary in your wrapper code
- If you hold an IO object, close it and pass the on-disk path instead
Example fix
# before
compiler.parse_file(Pathname.new('manifests/site.pp'))
# after
compiler.parse_file(Pathname.new('manifests/site.pp').to_s) Defensive patterns
Strategy: type-guard
Type guard
def string_path?(value) value.is_a?(String) && !value.empty? end raise ArgumentError, 'file must be a String path' unless string_path?(file)
Prevention
- Call .to_s on Pathname objects at API boundaries
- Keep a thin wrapper around PAL calls that enforces String arguments
When it happens
Trigger: parse_file(Pathname.new('manifests/site.pp')) after using Pathname/Dir tooling; parse_file(File.open('site.pp')) passing the handle instead of the path; any code path where the path variable was built from Pathname operations.
Common situations: Tooling that uses Pathname throughout; confusion caused by the documented [Path, String] type versus the String-only implementation; wrapping PAL in apps that model paths as objects.
Related errors
- The argument 'code_string' must be a String, got %{type}
- The argument 'puppet_code' must be a String, got %{type}
- Expected an instance of Puppet::SSL::Verifier but was passed
- The given 'ast' does not represent a literal value
- Given data_type value is not a data type, got '%{type}'
AI-assisted analysis of puppetlabs/puppet@e227c27540 (2026-08-21).
Data as JSON: /api/errors/0ca6475b3b67aa04.
Report an issue: GitHub.