You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Rails 7.1删除附件时Active Storage报Aws::S3::Errors::NoSuchKey错误求助

解决Rails 7.1 Active Storage搭配S3兼容存储时PurgeJob的NoSuchKey错误

问题场景

我在Rails 7.1应用中定义了带附件的User模型:

class User
  has_one_attached :avatar
end

使用Active Storage搭配Scaleway的S3兼容存储服务时,创建和删除附件的功能正常——删除后对象存储中的文件已消失,数据库中ActiveStorage::Attachment.count统计也正确,但Sidekiq执行ActiveStorage::PurgeJob时会抛出Aws::S3::Errors::NoSuchKey错误,日志如下:

10:42:10 sidekiq.1 | I, [2024-01-04T10:42:10.084390 #7886]  INFO -- :   S3 Storage (116.8ms) Deleted file from key: s9jppxubel7hc96a6dulvcd0hy1g
10:42:10 sidekiq.1 | I, [2024-01-04T10:42:10.123300 #7886]  INFO -- :   S3 Storage (126.2ms) Deleted file from key: 9ye6w1rfcxufsbjkh58xdq79jugm
10:42:10 sidekiq.1 | I, [2024-01-04T10:42:10.186220 #7886]  INFO -- :   S3 Storage (62.7ms) Deleted files by key prefix: variants/9ye6w1rfcxufsbjkh58xdq79jugm/
10:42:10 sidekiq.1 | E, [2024-01-04T10:42:10.186404 #7886] ERROR -- : Error performing ActiveStorage::PurgeJob (Job ID: 158ef8d0-0d3b-4438-b5f9-cfbbeed36561) from Sidekiq(default) in 199.24ms: Aws::S3::Errors::NoSuchKey (The specified key does not exist.):

经测试,DigitalOcean Spaces及纯净Rails 7.1.2应用均存在此问题,根源指向Active Storage的delete_prefixed方法。我的Active Storage配置如下:

scaleway:
  service: S3
  access_key_id: <%= ENV.fetch("SCALEWAY_S3_ACCESS_KEY_ID") %>
  secret_access_key: <%= ENV.fetch("SCALEWAY_S3_ACCESS_KEY_SECRET") %>
  region: <%= ENV.fetch("SCALEWAY_S3_REGION") %>
  bucket: <%= ENV.fetch("SCALEWAY_S3_BUCKET_NAME") %>
  endpoint: <%= ENV.fetch("SCALEWAY_S3_ENDPOINT") %>

解决方法

问题核心是:部分S3兼容存储(如Scaleway、DigitalOcean Spaces)对不存在的前缀执行批量删除时会抛出NoSuchKey错误,而AWS原生S3会忽略该情况返回成功。我们可以通过重写Active Storage的S3服务类来捕获这个异常:

  1. 在config/initializers目录下创建active_storage_s3_purge_fix.rb文件
  2. 添加以下代码:
require "active_storage/service/s3_service"

class ActiveStorage::Service::S3Service
  def delete_prefixed(prefix)
    instrument :delete_prefixed, prefix: prefix do
      bucket.objects(prefix: prefix).batch_delete!
    rescue Aws::S3::Errors::NoSuchKey
      # 忽略不存在前缀的错误,避免Sidekiq报错
    end
  end
end

该代码会覆盖原生的delete_prefixed方法,当执行批量删除遇到NoSuchKey错误时直接忽略,不会影响实际的删除逻辑(因为文件已经被成功删除,只是变体前缀可能不存在)。

内容的提问来源于stack exchange,提问作者basiszwo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 23:10:11