备份到 Cloudflare R2 在使用 aws-sdk-s3 1.182.0 进行多部分上传时失败(nil 没有 'downcase' 方法)

优先级/严重程度:

对于使用 S3 兼容备份存储的自托管实例,优先级为高,因为归档创建后计划备份会失败。

平台:

最新分支的自托管 Discourse。

观察时的当前运行版本:v2026.4.0-latest

Ruby: 3.4.0

aws-sdk-s3: 1.182.0

描述:

备份到 Cloudflare R2 在最后的“正在上传归档…”步骤失败。

数据库转储和本地归档创建均成功完成,但已完成备份归档的多部分上传失败。

实际结果:

备份失败,错误信息如下:

EXCEPTION: multipart upload failed: undefined method 'downcase' for nil

堆栈跟踪包含:

aws-sdk-s3-1.182.0/lib/aws-sdk-s3/multipart_file_uploader.rb
lib/backup_restore/s3_backup_store.rb:48
lib/backup_restore/creator.rb:434

预期结果:

备份归档应成功上传到配置的 S3 兼容备份存储。

可复现步骤:

  1. 使用 S3 兼容备份路径将备份存储配置为 Cloudflare R2。
  2. 使用大于多部分阈值的备份归档。
  3. 运行手动或计划备份。
  4. 观察“正在上传归档…”期间发生的失败。

相关配置:

  • DISCOURSE_BACKUP_LOCATION=s3
  • DISCOURSE_S3_ENDPOINT=https://.r2.cloudflarestorage.com
  • DISCOURSE_S3_FORCE_PATH_STYLE=true
  • DISCOURSE_S3_BACKUP_BUCKET=
  • AWS_REQUEST_CHECKSUM_CALCULATION=WHEN_REQUIRED
  • AWS_RESPONSE_CHECKSUM_VALIDATION=WHEN_REQUIRED

观察到的堆栈跟踪片段:

algorithm = resp.context.params[:checksum_algorithm]
k = "checksum_#{algorithm.downcase}".to_sym

这表明在多部分上传路径中,checksum_algorithm 为 nil。

其他背景信息:

Meta 上有一个类似的关于 Backblaze B2 的近期主题:

此外,1.182.0 之后的 aws-sdk-s3 更新日志条目也与此相关:

  • 1.201.0:修复多部分上传以在需要时尊重 request_checksum_calculation 模式
  • 1.210.2:在使用自定义端点或端点提供程序进行 PutObject 和 UploadPart 操作时,回退到使用头部请求校验和

Discourse 主分支目前似乎仍将 aws-sdk-s3 锁定在 1.182.0:

https://raw.githubusercontent.com/discourse/discourse/main/Gemfile.lock