kangkyu
kangkyu

Reputation: 6140

When is ActiveStorage::IntegrityError raised?

My app (locally) raises ActiveStorage::IntegrityError error, whenever it tries to attach a file. How can I get out of this error?

I have only one has_one_attached and I don't know how that error gets in the way.

# model
has_one_attached :it_file
Tempfile.open do |temp_file|
  # ...
  it_file.attach(io: temp_file, filename: 'filename.csv', content_type: 'text/csv')
end

# storage.yml
local:
  service: Disk
  root: <%= Rails.root.join("storage") %>

EDIT: it can be related with deleting storage/ directory (it happened after I deleted that) or it can be because it's happening in a job (the full error was Error performing ActivityJob (Job ID: .. ) from Async( .. ) in .. ms: ActiveStorage::IntegrityError (ActiveStorage::IntegrityError)

And this does not add files to storage/ folder but it's generating folders under it when I tried to attach them.

Upvotes: 21

Views: 13663

Answers (4)

Shiva
Shiva

Reputation: 12592

Background

In my case I faced this error when I was trying to upgrade the rails config defaults.

I was activating configs from config/initializers/new_framework_defaults_6_1.rb which was generated by rails app:update rake task.

Cause

I activated this setting

Rails.application.config.active_storage.track_variants = true

which collided with our existing mechanism to handle variant generation. We are reading variants size/types from account-settings so its complicated.

Technical cause

As mentioned above, this is causes due to mismatch in checksum of the file and checksum stored in blob record in database.

      # activestorage-6.1.7.1/lib/active_storage/downloader.rb:37

      def verify_integrity_of(file, checksum:)
        unless Digest::MD5.file(file).base64digest == checksum
          raise ActiveStorage::IntegrityError
        end
      end

Solution

  • I commented it back
  • To make sure its always inactive, I moved the setting to config/initializers/active_storage.rb like below

# Track Active Storage variants in the database.
# *Note*: Its Rails 6.1.0 feature and we have our own way of handling variants which also depends upon the
# thumbnail_sizes setting values and varies from account to account.
# so we are disabling it for now.
Rails.application.config.active_storage.track_variants = false

Summary

  • You may want to use this awesome feature so see workarounds.
  • In your case, causes can be something else so look deeper.
  • disabling this feature solves my issue.

Upvotes: 1

Guillermo Aguirre
Guillermo Aguirre

Reputation: 841

This was happening to me not because of anything mentioned above.

In my case I was defining a test var using one dummy file, but I was attaching it to 2 different records.

let(:file) { File.open(Rails.root.join('spec', 'fixtures', 'files', 'en.yml')) }
let(:data) { [file, file] }

The function in question received a list of ids and data and attaching the files to the records. This is a simplified version of the code

record_0.file.attach(
  io: data[0],
  filename: 'en.yml',
  content_type: 'application/x-yaml'
)
record_1.file.attach(
  io: data[1],
  filename: 'en.yml',
  content_type: 'application/x-yaml'
)

Once I defined 2 test vars, one for each record, using the same file I got it to work.

let(:file_0) { File.open(Rails.root.join('spec', 'fixtures', 'files', 'en.yml')) }
let(:file_1) { File.open(Rails.root.join('spec', 'fixtures', 'files', 'en.yml')) }
let(:data) { [file_0, file_1] }

Upvotes: 3

Aivils Štoss
Aivils Štoss

Reputation: 908

Very weird. After update to rails 6.0 I must recalculate some checksums. Yes I used dokku,docker. It was fine before update.

# Disk service is in use for ActiveStorage
class ProjectImage < ApplicationRecord
  has_one_attached :attachment
end

# update all checksums
ProjectImage.all.each do |image|
  blob = image.attachment.blob
  blob.update_column(:checksum, Digest::MD5.base64digest(File.read(blob.service.path_for(blob.key))))
end;

Upvotes: 6

Milo P
Milo P

Reputation: 1462

As mentioned in the comments, one reason this can happen is that the file object is at the end of the file, which was the problem in this case. It could be fixed here with temp_file.rewind.

Upvotes: 29

Related Questions