puppetlabs/puppet · error · ArgumentError

Cannot compare, as 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.

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.

Appendix: 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)