ActiveStorageで画像アップロードを行ったあとに非同期に実行される画像の解析処理で NameError ActiveStorage::AnalyzeJob uninitialized constant ActiveStorage::Analyzer::ImageAnalyzer::MiniMagick エラーが出た。
処理を行っているのはActiveStorage::Analyzer::ImageAnalyzer#read_imageの中。
def read_image download_blob_to_tempfile do |file| require "mini_magick" image = MiniMagick::Image.new(file.path) if image.valid? yield image else logger.info "Skipping image analysis because ImageMagick doesn't support the file" {} end end rescue LoadError logger.info "Skipping image analysis because the mini_magick gem isn't installed" {} rescue MiniMagick::Error => error logger.error "Skipping image analysis due to an ImageMagick error: #{error.message}" {} end
raiseされるのはL46のrescue節の中でMiniMagick::Error定数を参照しようとしたとき。
このタイミングでrequire "mini_magick"されていないので定数探索のときにActiveStorage::Analyzer::ImageAnalyzer以下を探すが見つからず、ActiveStorage::Analyzer::ImageAnalyzer::MiniMagick。
L33でrequire "mini_magick"されているはずなのに...と思ったが、発生原因は以下の通りだった。
- ブロック内の処理以前、
download_blob_to_tempfile内で別のエラーがraiseされている - L33で
require "mini_magick"する前にL46に到達し、定数が見つからずにNameErrorになる
別のエラーが何かというと、workerを実行するコンテナがS3の特定バケットに対する権限を持っておらず403 Forbiddenが返されている、というものだった(よくよくbacktraceを見ればAws::S3::Errors::Forbiddenが出力されていたことに同僚が気付いた)。
バケットを作るときに、アクセスするコンテナの指定を僕が忘れていただけだったので、権限をつけてもらって解決。
Sentryに飛んできたエラークラスが事象の根本となる問題を表していない(まれによくある)ので戸惑ったが解決できてよかった。