ruby/ruby · error · TypeError

wrong @requirements

Error message

wrong @requirements

What it means

When a Gem::Requirement is restored via Marshal (marshal_load validates that @requirements is an array whose elements are [op, Gem::Version] pairs; non-string ops are coerced to '='). A TypeError means the marshalled payload did not contain that shape - typically a corrupted or foreign marshal blob, e.g. a truncated specifications/*.gemspec cache file or data written by an incompatible layout.

Source

Thrown at lib/rubygems/requirement.rb:214

    requirements.map {|r| r.first == "~>" ? [r[0], r[1].to_s] : r }.sort.hash
  end

  def marshal_dump # :nodoc:
    [@requirements]
  end

  def marshal_load(array) # :nodoc:
    @requirements = array[0]

    if Array === @requirements
      return if @requirements.all? do |r|
        next false unless r.size == 2
        r[0] = "=" unless r.first.is_a?(String)
        r.last.is_a?(Gem::Version)
      end
    end

    raise TypeError, "wrong @requirements"
  end

  def yaml_initialize(tag, vals) # :nodoc:
    vals.each do |ivar, val|
      instance_variable_set "@#{ivar}", val
    end
  end

  def init_with(coder) # :nodoc:
    yaml_initialize coder.tag, coder.map
  end

  def encode_with(coder) # :nodoc:
    coder.add "requirements", @requirements
  end

  ##
  # A requirement is a prerelease if any of the versions inside of it

View on GitHub (pinned to 0e5b888e1c)

Solutions

  1. Reinstall the affected gem to regenerate its specification: `gem uninstall <gem> && gem install <gem>` or `gem pristine <gem>`
  2. Delete the corrupt marshalled spec file (the path usually appears in the backtrace under specifications/) and rerun the install
  3. For a broadly corrupted cache: `gem pristine --all` after ensuring a healthy disk and a single consistent RubyGems version per GEM_HOME
  4. Never hand-edit Marshal dumps; regenerate them from the source .gem

Example fix

# before
$ gem list -d  # => TypeError: wrong @requirements

# after
$ rm ~/.gem/specifications/broken_gem-1.0.gemspec
$ gem install broken_gem -v 1.0
Defensive patterns

Strategy: try-catch

Validate before calling

# sanity-check a marshal file before loading: marshal streams start with 0x04 0x08
abort 'not a Marshal stream' unless File.binread(path, 2) == "\x04\x08"
# and validate load results instead of trusting them

Try / catch

begin
  spec = Marshal.load(File.binread(spec_path))
rescue TypeError, ArgumentError
  warn "corrupt spec cache #{spec_path} - regenerating"
  File.delete(spec_path)
  retry_after_reinstall = true
end

Prevention

When it happens

Trigger: Marshal.load of a gem's marshalled specification where the requirements payload is corrupt (truncated file, disk/full-disk write, or data tampering); manually crafted Marshal streams fed into Gem::Requirement; loading spec caches copied between mismatched RubyGems installations.

Common situations: Interrupted `gem install` leaving a half-written .gemspec marshal file; disk-full or crash during cache updates; copying GEM_HOME/specifications between machines with different RubyGems versions; hand-editing marshal dumps.

Related errors


AI-assisted analysis of ruby/ruby@0e5b888e1c (2026-08-21). Data as JSON: /api/errors/d05d3a4cb5b49cff. Report an issue: GitHub.