puppetlabs/puppet · error · ArgumentError

Cannot compare, as %{other} is not a Rpm Version

Error message

Cannot compare, as %{other} is not a Rpm Version

What it means

Rpm#<=> (rpm.rb:42) raises ArgumentError 'Cannot compare, as X is not a Rpm Version' unless other.is_a?(self.class), then delegates to rpm_compare_evr on the string forms (epoch:version-release, epoch treated as zero when absent). eql?/== simply return false for foreign objects, but the spaceship operator must call into the RPM comparison library and refuses anything but another Rpm instance.

Source

Thrown at lib/puppet/util/package/version/rpm.rb:42

      version_found = ''.dup
      version_found += "#{@epoch}:" if @epoch
      version_found += @version
      version_found += "-#{@release}" if @release
      version_found
    end
    alias inspect to_s

    def eql?(other)
      other.is_a?(self.class) &&
        @epoch.eql?(other.epoch) &&
        @version.eql?(other.version) &&
        @release.eql?(other.release) &&
        @arch.eql?(other.arch)
    end
    alias == eql?

    def <=>(other)
      raise ArgumentError, _("Cannot compare, as %{other} is not a Rpm Version") % { other: other } unless other.is_a?(self.class)

      rpm_compare_evr(to_s, other.to_s)
    end

    private

    # overwrite rpm_compare_evr to treat no epoch as zero epoch
    # in order to compare version correctly
    #
    # returns 1 if a is newer than b,
    #         0 if they are identical
    #        -1 if a is older than b
    def rpm_compare_evr(a, b)
      a_hash = rpm_parse_evr(a)
      b_hash = rpm_parse_evr(b)

      a_hash[:epoch] ||= '0'
      b_hash[:epoch] ||= '0'

View on GitHub (pinned to e227c27540)

Solutions

  1. Parse both sides with Rpm.parse (accepts 'epoch:version-release.arch' shaped strings) before comparing.
  2. Type-guard comparisons: only call <=> when other.is_a?(Puppet::Util::Package::Version::Rpm).
  3. Convert foreign versions via their to_s into Rpm.parse when semantically valid.
  4. Rescue ArgumentError around sort/select blocks that may see mixed types and pre-normalize the array.

Example fix

// before
installed = Rpm.parse(pkg_version)
outdated = installed < latest_version_string # String -> ArgumentError

// after
latest = Puppet::Util::Package::Version::Rpm.parse(latest_version_string)
outdated = installed < latest
Defensive patterns

Strategy: type-guard

Type guard

RPM = Puppet::Util::Package::Version::Rpm
def rpm_pair?(a, b)
  a.is_a?(RPM) && b.is_a?(RPM)
end

Try / catch

begin
  a <=> b
rescue ArgumentError
  b = RPM.parse(b.to_s)
  a <=> b
end

Prevention

When it happens

Trigger: Puppet::Util::Package::Version::Rpm.parse('1:1.2.3-4.el7') > '1:1.2.3-5.el7' (String rhs); rpm_v < debian_v (cross-family compare); sorting an array mixing Rpm versions with Strings or Gem versions.

Common situations: Package code handling multiple package managers with a single generic comparator; ensure values pulled from RPM query output left as Strings on one side; refactors that changed one operand's parsing but not the other.

Related errors


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