{"record":{"id":"1b5f33b2c4117deb","repo":"puppetlabs/puppet","slug":"cannot-compare-this-this-class-with-othe","errorCode":null,"errorMessage":"Cannot compare #{this} (#{this.class}) with #{other} (Array). Only ±Float::INFINITY accepted.","messagePattern":"Cannot compare #(.+?) \\(#(.+?)\\) with #(.+?) \\(Array\\)\\. Only ±Float::INFINITY accepted\\.","errorType":"exception","errorClass":"Puppet::Error","httpStatus":null,"severity":"error","filePath":"lib/puppet/util/package/version/pip.rb","lineNumber":160,"sourceCode":"      end\n\n      [epoch, release_key, pre_key, post_key, dev_key, local_key]\n    end\n\n    def compare(this, other)\n      if (this.is_a? Array) && (other.is_a? Array)\n        this  << -Float::INFINITY if this.length < other.length\n        other << -Float::INFINITY if this.length > other.length\n\n        this.each_with_index do |element, index|\n          return compare(element, other.at(index)) if element != other.at(index)\n        end\n      elsif (this.is_a? Array) && !(other.is_a? Array)\n        raise Puppet::Error, \"Cannot compare #{this} (Array) with #{other} (#{other.class}). Only ±Float::INFINITY accepted.\" unless other.abs == Float::INFINITY\n\n        return other == -Float::INFINITY ? 1 : -1\n      elsif !(this.is_a? Array) && (other.is_a? Array)\n        raise Puppet::Error, \"Cannot compare #{this} (#{this.class}) with #{other} (Array). Only ±Float::INFINITY accepted.\" unless this.abs == Float::INFINITY\n\n        return this == -Float::INFINITY ? -1 : 1\n      end\n      this <=> other\n    end\n\n    class ValidationFailure < ArgumentError\n      def initialize(version)\n        super(\"#{version} is not a valid python package version. Please refer to https://www.python.org/dev/peps/pep-0440/.\")\n      end\n    end\n  end\nend\n","sourceCodeStart":142,"sourceCodeEnd":174,"githubUrl":"https://github.com/puppetlabs/puppet/blob/e227c27540975c25aa22d533a52424a9d2fc886a/lib/puppet/util/package/version/pip.rb#L142-L174","documentation":"Mirror of the previous guard in Pip.compare (pip.rb:160): the LEFT comparison key is a non-Array scalar and the RIGHT is an Array. The scalar must be +/- Float::INFINITY (the sentinel used by #key for missing segments); any finite value raises Puppet::Error 'Only ±Float::INFINITY accepted.' before the comparison can proceed.","triggerScenarios":"Same shape as 1006 with sides swapped: comparing a hand-built/stale key whose slot holds a finite Integer/Float (e.g., an epoch-style number left in the release position) against a properly parsed version whose release/local key is an Array; a stubbed peer object returning a scalar from #key where the real class returns an Array.","commonSituations":"Stale serialized version objects compared after a puppet upgrade changed #key's shape; test fixtures constructing key arrays by hand; caches (memoization) shared across versions of the class.","solutions":["Rebuild both operands via Pip.parse immediately before comparing; never compare cached/stubbed key data.","Freeze/re-parse cache entries when the library version changes; include the puppet version in the cache key.","In specs, use parsed instances instead of objects with fabricated instance variables.","Rescue Puppet::Error at the comparison boundary and re-parse once as a recovery path."],"exampleFix":"// before\nsorted = cached_versions.sort # one entry has a stale scalar key element\n\n// after\nsorted = cached_versions.map { |v| Puppet::Util::Package::Version::Pip.parse(v.to_s) }.sort","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"PIP = Puppet::Util::Package::Version::Pip\ndef pip_instances?(*versions)\n  versions.all? { |v| v.is_a?(PIP) }\nend","tryCatchPattern":"begin\n  sorted = versions.sort\nrescue Puppet::Error => e\n  raise unless e.message.include?('Only ±Float::INFINITY')\n  versions.map! { |v| PIP.parse(v.to_s) }\n  retry\nend","preventionTips":["Re-parse both operands from to_s before comparing when any doubt exists about their origin.","Avoid monkey-patching or dup-and-mutating version objects.","Fail loudly in dev when key shapes differ instead of letting sort blow up in production."],"tags":["pip","python","pep-440","version-comparison","invariant","internal-error"],"backgroundTag":"invalid-version-comparison","analyzedSha":"e227c27540975c25aa22d533a52424a9d2fc886a","analyzedAt":"2026-08-21T20:49:46.650Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}