Mini_magick is required inside `download_blob_to_tempfile` block but used outside

In ActiveStorage::Analyzer::ImageAnalyzer::ImageMagick#read_image

require "mini_magick" is called inside the block passed to download_blob_to_tempfile. However, it is used outside that block at L30:

rescue MiniMagick::Error => error

That means if download_blob_to_tempfile raises an error and mini_magick hasn’t been previously required, L30 raises a NameError instead of skipping the rescue block and propagating the error.

The fix seems really simple: inverse L13 and L14 to require mini_magick at the level it is used.

Did you observe the NameError you described? By reading the flow of this code it seems to me that the rescue clause can only get triggered after the L14 require is executed, because Minimagick errors are apparently raised only starting at L17.

Yes, it occurred in my code.

The issue is not errors raised by mini_magick, but when an error is trigger by download_blob_to_tempfile before yielding the block.

In my case, the file couldn’t be found on the remote storage. Therefore the block is never called, mini_magick is never required, and the rescue fails because the exception MiniMagick::Error hasn’t been defined.

Ok understood, thanks for the explanation, it sounds worth submitting a PR :slightly_smiling_face:

The thing is I tried to reproduce inside the corresponding test but require is called separately, and even if I bypass the call, it’s already required by previous tests. So I can submit a PR but I really don’t see how to attach a test or even a script to reproduce the issue.

Why is require called separately in the test, if the code being tested already takes care of it?

Maybe you could undefine Minimagick before the test begins.

It seems like the test is designed so the test suite will pass on a machine that doesn’t have mini_magick and depends on the require to assert it.

The other issue is that mini_magick may be required by a previous test.

That being said, the potential issue and change seem pretty self-explanatory, so maybe we’re fine as long as the existing tests still pass?

That being said, the potential issue and change seem pretty self-explanatory, so maybe we’re fine as long as the existing tests still pass?

I would assume so.