moneta-rb / moneta

a unified interface to key/value stores
https://github.com/moneta-rb/moneta
MIT License
1.12k stars 87 forks source link

too many arguments for format string, seemingly only when `ruby -d` #227

Open zenspider opened 2 years ago

zenspider commented 2 years ago

On rails boot we've got a bunch of stuff loading and normally everything works fine. HOWEVER, whenever I try to debug something by running rails boot via ruby -d (aka $DEBUG = true), rails bootstrap blows out thusly:

GEMS/moneta-1.5.1/lib/moneta/transformer.rb:359:in `%': too many arguments for format string (ArgumentError)
    from GEMS/moneta-1.5.1/lib/moneta/transformer.rb:359:in `block in compile_transformer'
    from GEMS/moneta-1.5.1/lib/moneta/transformer.rb:348:in `each'
    from GEMS/moneta-1.5.1/lib/moneta/transformer.rb:348:in `compile_transformer'
    from GEMS/moneta-1.5.1/lib/moneta/transformer.rb:65:in `compile'
    from GEMS/moneta-1.5.1/lib/moneta/transformer.rb:38:in `new'
    from GEMS/moneta-1.5.1/lib/moneta/builder.rb:65:in `new_proxy'
    from GEMS/moneta-1.5.1/lib/moneta/builder.rb:25:in `block in build'
    from GEMS/moneta-1.5.1/lib/moneta/builder.rb:23:in `each'
    from GEMS/moneta-1.5.1/lib/moneta/builder.rb:23:in `inject'
    from GEMS/moneta-1.5.1/lib/moneta/builder.rb:23:in `build'
    from GEMS/moneta-1.5.1/lib/moneta.rb:167:in `build'
    from GEMS/moneta-1.5.1/lib/moneta.rb:145:in `new'
... lots

I don't know if debug mode is changing the args going to that string format, or if debug mode is disabling something that's swallowing this exception and it is happening all the time.

I've doped the run to print out the format string:

# normal run:
{:CODE=>"::Marshal.dump(%s)"}
{:CODE=>"(options[:prefix] || @prefix)+%s"}
{:CODE=>"%s.sub(@prefix, '')"}
{:CODE=>"::Marshal.load(%s)"}
{:CODE=>"%s.start_with?(@prefix)"}
{:CODE=>"::Marshal.load(%s)"}
{:CODE=>"(::Marshal.load(key.start_with?(@prefix)) rescue '')"}
{:CODE=>"::Marshal.dump(%s)"}
{:CODE=>"::Marshal.load(%s)"}

vs:

# debug run:
{:CODE=>"::Marshal.dump(%s)"}
{:CODE=>"(options[:prefix] || @prefix)+%s"}
{:CODE=>"%s.sub(@prefix, '')"}
{:CODE=>"::Marshal.load(%s)"}
{:CODE=>"%s.start_with?(@prefix)"}
{:CODE=>"::Marshal.load(%s)"}
{:CODE=>"(::Marshal.load(key.start_with?(@prefix)) rescue '')"}

So I think since the last marshal line doesn't have %s on both sides, I suspect someone is swallowing that exception.

It LOOKS like this is being hit:

      def compile_prefix(name:, transformer:, value:)
        return unless [:encode, :serialize].include?(transformer[0])

        load_val, = compile_transformer([name], value, 1)
        "(#{load_val} rescue '')"
      end

and the result of that doesn't have a %s and gets passed to format.

zenspider commented 2 years ago

Come to think of it... this just doesn't make sense:

::Marshal.load(key.start_with?(@prefix))
asppsa commented 2 years ago

Hey, thanks for the report. I've got covid right now, but will take a look at this when I can. If you work out how to fix this a PR would be most welcome