{"record":{"id":"fd9c4daca652dc4e","repo":"ruby/ruby","slug":"unable-to-call-method-inspect-on-receiver-ins","errorCode":null,"errorMessage":"Unable to call #{method.inspect} on #{receiver.inspect}, perhaps it is a class using marshal compat, which is not visible in ruby? #{e}","messagePattern":"Unable to call #(.+?) on #(.+?), perhaps it is a class using marshal compat, which is not visible in ruby\\? #(.+?)","errorType":"exception","errorClass":"Gem::SafeMarshal::Visitors::ToRuby::MethodCallError","httpStatus":null,"severity":"error","filePath":"lib/rubygems/safe_marshal/visitors/to_ruby.rb","lineNumber":369,"sourceCode":"          when Elements::SymbolLink\n            visit_Gem_SafeMarshal_Elements_SymbolLink(element).to_s\n          else\n            raise FormatError, \"Expected symbol or symbol link, got #{element.inspect} @ #{formatted_stack.join(\".\")}\"\n          end\n        end\n      end\n\n      def register_object(o)\n        @objects << o\n        o\n      end\n\n      def call_method(receiver, method, *args)\n        receiver.__send__(method, *args)\n      rescue NoMethodError => e\n        raise unless e.receiver == receiver\n\n        raise MethodCallError, \"Unable to call #{method.inspect} on #{receiver.inspect}, perhaps it is a class using marshal compat, which is not visible in ruby? #{e}\"\n      end\n\n      def formatted_stack\n        formatted = []\n        @stack[0, @stack_idx].each do |e|\n          if e.is_a?(Integer)\n            if formatted.last == \"ivar_\"\n              formatted[-1] = \"ivar_#{e}\"\n            else\n              formatted << \"[#{e}]\"\n            end\n          else\n            formatted << e\n          end\n        end\n        formatted\n      end\n","sourceCodeStart":351,"sourceCodeEnd":387,"githubUrl":"https://github.com/ruby/ruby/blob/0e5b888e1c355f3f728f2659f085820937dada48/lib/rubygems/safe_marshal/visitors/to_ruby.rb#L351-L387","documentation":"RubyGems reads Ruby Marshal 4.8 streams (gem metadata, the specs.4.8.gz source caches, Bundler's marshalled dependency responses) through its SafeMarshal reader and converts them into real objects with the ToRuby visitor. For UserDefined/UserMarshal sections the visitor must dispatch methods like :_load (only Time and Gem::Specification are permitted), :allocate, and :marshal_load on the resolved class; if that call raises a NoMethodError owned by the receiver itself, it is re-raised as Gem::SafeMarshal::Visitors::ToRuby::MethodCallError. The 'marshal compat' wording refers to COMPAT_CLASSES (Rational is rebuilt through an internal RationalCompat that user code never sees).","triggerScenarios":"Gem::SafeMarshal.safe_load (called from Gem::Specification.load, Gem::Source#load_specs, Gem::NameTuple.from_list, Bundler.safe_load_marshal) on a stream whose UserDefined/UserMarshal class name resolves to a constant that lacks _load, :allocate, or :marshal_load — e.g. the name resolves to a Module (modules do not respond to allocate), a shadowed constant, or a stub class.","commonSituations":"Corrupted or truncated specs.4.8.gz cache after a network drop or crash; a partially downloaded .gem whose metadata.gz is cut off; a gem or plugin that defines a top-level constant shadowing Time, Rational, or Gem::Specification; hand-edited or malicious marshal payloads.","solutions":["Clear the stale marshal caches and refetch: `gem sources -u` for the specs cache, remove the copied gem from the install dir, and re-download the .gem from the source","If it happens during `bundle install`, delete the local marshal cache (e.g. ~/.bundle/cache, vendor/cache copies) so Bundler refetches; Bundler itself falls back to the slower YAML endpoint when it rescues this error","Verify the .gem integrity: re-download it and compare checksums, or run `gem specification pkg.gem` to see if the metadata parses at all","If you control the data producer, ensure the marshal stream only embeds Time, Gem::Specification, and Rational as custom classes","If a local constant shadows a permitted class (e.g. your own Time class), rename it or load the gem metadata in a subprocess without that constant defined"],"exampleFix":"# before\nspec = Gem::SafeMarshal.safe_load(data)\n\n# after\nbegin\n  spec = Gem::SafeMarshal.safe_load(data)\nrescue Gem::SafeMarshal::Visitors::ToRuby::Error => e\n  # cache is unusable; refetch from source like Bundler does\n  spec = refetch_spec_from_source\nend","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"begin\n  data = Gem::SafeMarshal.safe_load(marshal_bytes)\nrescue Gem::SafeMarshal::Visitors::ToRuby::MethodCallError => e\n  # treat source as corrupt: refetch or fall back (this is Bundler's own pattern)\n  data = refetch_or_fallback\nend","preventionTips":["Treat marshal caches (specs.4.8.gz, .gem metadata) as disposable — refetch on any parse failure","Never let app code define constants named Time, Rational, or Gem::Specification at top level","Pin rubygems and bundler to compatible versions in CI to keep reader/visitor consistent","Verify downloads (checksums/size) before caching marshal payloads"],"tags":["rubygems","marshal","deserialization","cache-corruption","safemarshal"],"backgroundTag":"marshal-deserialization-failed","analyzedSha":"0e5b888e1c355f3f728f2659f085820937dada48","analyzedAt":"2026-08-21T14:25:43.473Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}