Raise Dalli::UnmarshalError on ArgumentError "dump format error (user class)" #1008
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This PR makes Rails recognize the unmarshalling error and can deal with it normally.
Before this change, such an ArgumentError would bubble up and raise in Rails.
Details
In Marshal, a "user class" is a class which extends a "core class" (String, Hash...).
When a "user class" is dumped by
Marshal.dump
, it becomes a binary string.Marshal.load
, expects that the inheritance of this class looks the same as it did when the binary string was created.If the classes do not match, due to some change in the code, an ArgumentError is raised. (The specific ArgumentError is raised in marshal.c.)
Marshal's concept of "user class" is explained in: "Caching With MessagePack" by Chris Salzberg at RubyKaigi 2022
Context for Rails
This Rails commit, which is in Rails 7.1, rails/rails@a6be798, expects Dalli to reraise such errors, so that Rails can decide to regenerate that cache entry.
Between 7.0 and 7.1 Rails changed the inheritance hierarchy in its String-extending classes OutputBuffer and SafeBuffer, which triggered this error in production for me.
Further
In #1009 I made the regular expression-making code a little easier to read, using Regexp.union.
But, later, in #1011, I made a wider change, reraising Dalli::UnmarshalError for all errors raised during
serializer.load
. It's a simplification of the code, of the solution, but takes more steps than this tiny change.EDIT: I posted a feature request in bugs.ruby-lang.org for having error classes for these ArgumentError instances, instead. (Perhaps they can become 1 error, (
class UnmarshalingError < ArgumentError
), or something.)