instructure/canvas-lms · error · ThumbnailError

source image too large

Error message

source image too large

What it means

attachment_fu's mini_magick processor raises ThumbnailError in process_attachment when the source image's pixel area (width*height) exceeds the configured :thumbnail_max_image_size_pixels limit. The gem refuses to load/process images that could exhaust memory or CPU during resizing. It is a deliberate safety guard, not a corrupt-file error.

Solutions

  1. Resize or re-export the source image below the configured pixel limit before uploading
  2. Raise (or remove) the :thumbnail_max_image_size_pixels option on the attachment model's has_attachment call
  3. Pre-process oversized images with an external tool (ImageMagick mogrify -resize) or a background job that downscales before process_attachment runs
  4. Handle ThumbnailError in the upload flow and surface a friendly message asking users to upload a smaller image

Example fix

# before
has_attachment content_type: :image, max_size: 50.megabytes
# after
has_attachment content_type: :image, max_size: 50.megabytes,
  thumbnail_max_image_size_pixels: 100_000_000
Defensive patterns

Strategy: try-catch

Validate before calling

if img[:width] * img[:height] > max_image_size
  raise UploadTooLarge, 'please upload a smaller image'
end

Type guard

def within_pixel_limit?(width, height, limit)
  limit.nil? || width * height <= limit
end

Try / catch

begin
  attachment.save
rescue ThumbnailError => e
  Rails.logger.warn(e.message)
  render json: { error: 'Image dimensions exceed the allowed maximum' }, status: :unprocessable_entity
end

Prevention

When it happens

Trigger: Uploading/resizing an image whose width*height exceeds attachment_options[:thumbnail_max_image_size_pixels] while image? is true and the attachment has not yet been resized (@resized is nil). Happens in the mini_magick processing pipeline (with_image block) before resize_image_or_thumbnail! runs.

Common situations: Users upload very high-resolution photos (e.g. 50MP) to a Canvas/SitePress-style attachment model with the pixel guard configured; the limit was set for thumbnails but the original attachment goes through the same processor; an account raises upload size limits without adjusting the pixel cap.

Understand the failure class

Background: "File too large" / "file size exceeds limit" errors: why libraries cap file sizes and how to fix them — this error's family across 46 libraries.

Related errors


AI-assisted analysis of instructure/canvas-lms@1c9f0bb801 (2026-09-15). Data as JSON: /api/errors/0f33aca89bcb622b. Report an issue: GitHub.

Appendix: source

Thrown at gems/attachment_fu/lib/attachment_fu/processors/mini_magick_processor.rb:51

            binary_data = file.is_a?(MiniMagick::Image) ? file : MiniMagick::Image.open(file) if Object.const_defined?(:MiniMagick)
          rescue
            # Log the failure to load the image.
            logger.debug("Exception working with image: #{$!}")
            binary_data = nil
          end
          yield binary_data if block_given? && binary_data
        end
      end

      protected

      def process_attachment
        return unless super

        if image? && !@resized
          with_image do |img|
            max_image_size = attachment_options[:thumbnail_max_image_size_pixels]
            raise ThumbnailError, "source image too large" if max_image_size && img[:width] * img[:height] > max_image_size

            resize_image_or_thumbnail! img
            self.width = img[:width] if respond_to?(:width)
            self.height = img[:height] if respond_to?(:height)
            @resized = true
          end
        end
      rescue MiniMagick::Error => e
        logger.warn("MiniMagick processing failed: #{e}")
      end

      # Performs the actual resizing operation for a thumbnail
      def resize_image(img, size)
        size = size.first if size.is_a?(Array) && size.length == 1
        img.combine_options do |commands|
          commands.strip unless attachment_options[:keep_profile]

          commands.limit("area", "100MB")

View on GitHub (pinned to 1c9f0bb801)