puppetlabs/puppet · error · Puppet::Util::Package::Version::Range::ValidationFailure
Operator '#{operator}' is not implemented
Error message
Operator '#{operator}' is not implemented What it means
The operator dispatch in Range.parse (range.rb:51): FULL_REGEX happily captures ANY run of [<>=] characters as the 'operator', but the case statement only implements '>', '>=', '<', '<=' and '' (empty = exact equality). Any other captured operator falls to else and raises ValidationFailure 'Operator ... is not implemented'.
Source
Thrown at lib/puppet/util/package/version/range.rb:51
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"
end
end
simples.size == 1 ? simples[0] : MinMax.new(simples[0], simples[1])
end
end
end
View on GitHub (pinned to e227c27540)
Solutions
- For exact pins, drop the operator entirely: Range.parse('1.2.3', klass) maps to Eq.
- Translate equality syntax before parsing: replace '==' or '=' at token start with ''.
- Whitelist-validate tokens: /\A(?:>=|<=|>|<)?[^<>=]+\Z/ before handing to parse.
- Rescue Range::ValidationFailure and surface a message listing supported operators > >= < <= and bare version.
Example fix
// before rng = Puppet::Util::Package::Version::Range.parse(ensure_spec, klass) # ensure_spec = '==1.26.0' // after spec = ensure_spec.strip.gsub(/\A==?/, '') rng = Puppet::Util::Package::Version::Range.parse(spec, klass) # '1.26.0' -> Eq
Defensive patterns
Strategy: validation
Validate before calling
SUPPORTED = /\A(?:>=|<=|>|<)?(?!=)[^<>=]+\z/ return :invalid unless constraint.match?(SUPPORTED)
Try / catch
begin
Range.parse(constraint, version_class)
rescue Puppet::Util::Package::Version::Range::ValidationFailure => e
raise e if e.message.include?('not implemented')
raise
end Prevention
- Translate '=='/'=' pins to a bare version before Range.parse.
- Whitelist the operator vocabulary at the input boundary and reject anything else with a clear message.
When it happens
Trigger: Range.parse('==1.0', klass) (pip/gem equality syntax -> operator '=='), Range.parse('=1.0', klass) (single '=' is a captured operator, NOT the empty/Equality case -> raise), Range.parse('=>1.0', klass), Range.parse('<>1.0', klass), Range.parse('>>1', klass).
Common situations: Constraints copied from requirements.txt ('==1.26.0') or Gemfile ('= 1.0'); npm-style '^1.2.3' would instead fail the FULL_REGEX match (caret is captured by (.+) as part of the version and then fails version_class.parse); users assuming '=' means pinned.
Related errors
- Unable to parse '#{range_string}' as a string
- Unable to parse '#{simple}' as a version range identifier
- Invalid 'version_range' field in metadata.json: %{err}
- Unable to parse '#{ver}' as a debian version identifier
- #{version} is not a valid ruby gem version.
AI-assisted analysis of puppetlabs/puppet@e227c27540 (2026-08-21).
Data as JSON: /api/errors/212a52cc7621e50f.
Report an issue: GitHub.