{"record":{"id":"9d8bf396f4e70202","repo":"ruby/ruby","slug":"attempting-to-visit-unknown-element-e-inspect","errorCode":null,"errorMessage":"Attempting to visit unknown element #{e.inspect}","messagePattern":"Attempting to visit unknown element #(.+?)","errorType":"exception","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"lib/rubygems/safe_marshal/visitors/visitor.rb","lineNumber":21,"sourceCode":"module Gem::SafeMarshal::Visitors\n  class Visitor\n    def visit(target)\n      send DISPATCH.fetch(target.class), target\n    end\n\n    private\n\n    DISPATCH = Gem::SafeMarshal::Elements.constants.each_with_object({}) do |c, h|\n      next if c == :Element\n\n      klass = Gem::SafeMarshal::Elements.const_get(c)\n      h[klass] = :\"visit_#{klass.name.gsub(\"::\", \"_\")}\"\n      h.default = :visit_unknown_element\n    end.compare_by_identity.freeze\n    private_constant :DISPATCH\n\n    def visit_unknown_element(e)\n      raise ArgumentError, \"Attempting to visit unknown element #{e.inspect}\"\n    end\n\n    def visit_Gem_SafeMarshal_Elements_Array(target)\n      target.elements.each {|e| visit(e) }\n    end\n\n    def visit_Gem_SafeMarshal_Elements_Bignum(target); end\n    def visit_Gem_SafeMarshal_Elements_False(target); end\n    def visit_Gem_SafeMarshal_Elements_Float(target); end\n\n    def visit_Gem_SafeMarshal_Elements_Hash(target)\n      target.pairs.each do |k, v|\n        visit(k)\n        visit(v)\n      end\n    end\n\n    def visit_Gem_SafeMarshal_Elements_HashWithDefaultValue(target)","sourceCodeStart":3,"sourceCodeEnd":39,"githubUrl":"https://github.com/ruby/ruby/blob/0e5b888e1c355f3f728f2659f085820937dada48/lib/rubygems/safe_marshal/visitors/visitor.rb#L3-L39","documentation":"The SafeMarshal base visitor dispatches each parsed element through a table (DISPATCH) built from every constant under Gem::SafeMarshal::Elements; the table's default routes any unrecognized element class to visit_unknown_element, which raises ArgumentError. Reaching it means the element object being visited is not one of the known element types — normally an internal version skew between the reader that produced the elements and the visitor consuming them, or a foreign/monkey-patched element class.","triggerScenarios":"Feeding the visitor element objects not defined in Gem::SafeMarshal::Elements: mixing a newer reader (which emits new element types) with an older visitor from another rubygems/bundler version, calling Gem::SafeMarshal::Visitors::ToRuby#visit directly on a hand-built element tree, or a gem monkey-patching the reader to introduce custom element classes.","commonSituations":"Vendored or pinned old rubygems/Bundler running next to newer installed components; internal API misuse by a tool that constructs element objects itself; rare corrupted streams that decode into unexpected structure.","solutions":["Align versions: update rubygems and bundler together (`gem update --system`, `bundle update --bundler`) so the reader and visitor come from the same release","Remove or update any gem/plugin that monkey-patches Gem::SafeMarshal internals","If you call the visitor directly, only pass elements produced by Gem::SafeMarshal::Reader from the same rubygems version","Rescue ArgumentError around the safe_load call and treat the payload as unparseable (refetch or reject)"],"exampleFix":"# before\ndef render(elements)\n  visitor.visit(elements)\nend\n\n# after\nbegin\n  visitor.visit(elements)\nrescue ArgumentError => e\n  raise if e.message !~ /unknown element/\n  # reader/visitor mismatch: regenerate elements with the current reader\nend","handlingStrategy":"try-catch","validationCode":null,"typeGuard":"known_element = ->(e) { Gem::SafeMarshal::Elements.constants.any? { |c| Gem::SafeMarshal::Elements.const_get(c) === e } }","tryCatchPattern":"begin\n  visitor.visit(element)\nrescue ArgumentError => e\n  raise unless e.message.include?('unknown element')\n  # reader/visitor version skew: regenerate or reject payload\nend","preventionTips":["Update rubygems and bundler together so reader and visitor ship from one release","Do not monkey-patch Gem::SafeMarshal reader/element internals","Only feed the visitor elements produced by the matching reader version"],"tags":["rubygems","marshal","safemarshal","version-mismatch","internal-api"],"backgroundTag":"unsupported-serialization-format","analyzedSha":"0e5b888e1c355f3f728f2659f085820937dada48","analyzedAt":"2026-08-21T14:25:43.473Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}