valid,invalid

関心を持てる事柄について

NameError uninitialized constant ActiveStorage::Analyzer::ImageAnalyzer::MiniMagick

ActiveStorageで画像アップロードを行ったあとに非同期に実行される画像の解析処理で NameError ActiveStorage::AnalyzeJob uninitialized constant ActiveStorage::Analyzer::ImageAnalyzer::MiniMagick エラーが出た。

処理を行っているのはActiveStorage::Analyzer::ImageAnalyzer#read_imageの中。

https://github.com/rails/rails/blob/v6.1.4/activestorage/lib/active_storage/analyzer/image_analyzer.rb#L31-L49

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に飛んできたエラークラスが事象の根本となる問題を表していない(まれによくある)ので戸惑ったが解決できてよかった。