puppetlabs/puppet · error · Puppet::Util::Package::Version::Range::ValidationFailure
Unable to parse '#{range_string}' as a string
Error message
Unable to parse '#{range_string}' as a string What it means
Puppet::Util::Package::Version::Range.parse (range.rb:33) raises ValidationFailure unless range_string.is_a?(String). The parser then splits on whitespace and interprets each token as an optional operator (> >= < <=) plus a version, delegating version parsing to the supplied version_class (Debian/Gem/Pip).
Source
Thrown at lib/puppet/util/package/version/range.rb:33
# Currently parsed version range string may take any of the following
# forms:
#
# * Regular Version strings
# * ex. `"1.0.0"`, `"1.2.3-pre"`
# * Inequalities
# * ex. `">1.0.0"`, `"<3.2.0"`, `">=4.0.0"`
# * Range Intersections (min is always first)
# * ex. `">1.0.0 <=2.3.0"`
#
RANGE_SPLIT = /\s+/
FULL_REGEX = /\A((?:[<>=])*)(.+)\Z/
# @param range_string [String] the version range string to parse
# @param version_class [Version] a version class implementing comparison operators and parse method
# @return [Range] a new {Range} instance
# @api public
def self.parse(range_string, version_class)
raise ValidationFailure, "Unable to parse '#{range_string}' as a string" unless range_string.is_a?(String)
simples = range_string.split(RANGE_SPLIT).map do |simple|
match, operator, version = *simple.match(FULL_REGEX)
raise ValidationFailure, "Unable to parse '#{simple}' as a version range identifier" unless match
case operator
when '>'
Gt.new(version_class.parse(version))
when '>='
GtEq.new(version_class.parse(version))
when '<'
Lt.new(version_class.parse(version))
when '<='
LtEq.new(version_class.parse(version))
when ''
Eq.new(version_class.parse(version))
else
raise ValidationFailure, "Operator '#{operator}' is not implemented"View on GitHub (pinned to e227c27540)
Solutions
- Join token arrays first: Range.parse(tokens.join(' '), version_class).
- Check for nil/blank input before calling: return a default (e.g., Eq of the current version) when unset.
- Type-guard with is_a?(String) and raise a descriptive error of your own naming the parameter.
- Rescue Range::ValidationFailure (ArgumentError subclass) at input boundaries.
Example fix
// before
rng = Puppet::Util::Package::Version::Range.parse(params[:version_range], Debian) # nil
// after
raw = params[:version_range]
rng = if raw.is_a?(String) && !raw.strip.empty?
Puppet::Util::Package::Version::Range.parse(raw, Debian)
else
Puppet::Util::Package::Version::Range::Eq.new(Debian.parse(default_version))
end Defensive patterns
Strategy: type-guard
Validate before calling
def range_string?(v) v.is_a?(String) && !v.strip.empty? end
Type guard
def range_input?(v) v.is_a?(String) end
Try / catch
begin Puppet::Util::Package::Version::Range.parse(str, version_class) rescue Puppet::Util::Package::Version::Range::ValidationFailure nil end
Prevention
- Join token arrays and stringify symbols before calling Range.parse.
- Give unset constraints an explicit default (bare current version) instead of passing nil.
When it happens
Trigger: Range.parse(nil, Debian), Range.parse(['>1.0'], Gem) (array of tokens instead of joined string), Range.parse(range_object, version_class) (passing an already-parsed Gt/Eq instance back in), Range.parse(:'>=1.0', Pip) (symbol).
Common situations: nil default when a manifest parameter is unset; arrays from data bindings passed unjoined; round-tripping parsed ranges through code that expects raw strings.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- #{version} is not a valid ruby gem version.
- Unable to parse '#{simple}' as a version range identifier
- Operator '#{operator}' is not implemented
- field 'data_provider' must be a string
- Invalid 'version_range' field in metadata.json: %{err}
AI-assisted analysis of puppetlabs/puppet@e227c27540 (2026-08-21).
Data as JSON: /api/errors/23e935bd9dc6e422.
Report an issue: GitHub.