ActiveStorage now raises a PreviewError when previews fail to generate


ActiveStorage provides wonderful out-of-the-box tools to handle all things related to storing files and media. One of its key features is preview generation. Often once a user uploads a file (an image or PDF), we would require a preview to be generated to be used all across the website.

Preview generation in ActiveStorage is handled at its core by the Poppler gem. It is extremely robust – most of the time. However, if a preview cannot be generated, the IO stream that is captured is empty, resulting in a 0-byte preview file being generated and stored in the Active Storage service.

This causes various errors across the applications that we as developers must now handle. However, the latest update to ActiveStorage now raises a PreviewError when previews fail to generate.

Before

When Poppler fails to generate previews, it creates 0-byte files. Performing any actions on these files, such as resizing would result in various other unpredictable errors. Poppler’s Previewer must not proceed normally, if the child process that attempted to capture a preview exited unsuccessfully.

After

The latest update in Rails 7 raises an exception, called PreviewError if the previewer child process exits with a non-0 status code.

def capture(*argv, to:)
  to.binmode

  open_tempfile do |err|
    IO.popen(argv, err: err) { |out| IO.copy_stream(out, to) }
    err.rewind

    unless $?.success?
      raise PreviewError, "#{argv.first} failed (status #{$?.exitstatus}): #{err.read.to_s.chomp}"
    end
  end

  to.rewind
end

This allows developers to make contingency plans for previews right at the source – avoiding messy and unpredictable errors later on.

Check out the commit to know more.