Priority/Severity:
High for self-hosted instances using S3-compatible backup storage, because scheduled backups fail after archive creation.
Platform:
Self-hosted Discourse on latest branch.
Current live version when observed: v2026.4.0-latest
Ruby: 3.4.0
aws-sdk-s3: 1.182.0
Description:
Backups to Cloudflare R2 fail at the final “Uploading archive…” step.
The database dump and local archive creation complete successfully, but multipart upload of the finished backup archive fails.
Actual result:
The backup fails with:
EXCEPTION: multipart upload failed: undefined method 'downcase' for nil
Stack trace includes:
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
Expected result:
The backup archive should upload successfully to the configured S3-compatible backup store.
Reproducible steps:
- Configure backup storage to Cloudflare R2 using the S3-compatible backup path.
- Use a backup archive larger than the multipart threshold.
- Run a manual or scheduled backup.
- Observe failure during “Uploading archive…”.
Relevant configuration:
- 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
Observed stack trace excerpt:
algorithm = resp.context.params[:checksum_algorithm]
k = "checksum_#{algorithm.downcase}".to_sym
This suggests checksum_algorithm is nil in the multipart upload path.
Additional context:
There is a similar recent Meta topic for Backblaze B2:
Also, aws-sdk-s3 changelog entries after 1.182.0 appear relevant:
- 1.201.0: Fix multipart upload to respect request_checksum_calculation when_required mode
- 1.210.2: Falls back to header request checksums when using custom endpoints or endpoint providers for PutObject and UploadPart operations
Discourse main currently still appears to lock aws-sdk-s3 to 1.182.0:
https://raw.githubusercontent.com/discourse/discourse/main/Gemfile.lock