aws-sdk-s3 1.182.0에서 다중 부분 업로드 시 Cloudflare R2 백업 실패 (undefined method 'downcase' for nil)

우선순위/심각도:

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임을 시사합니다.

추가 컨텍스트:

Backblaze B2에 대한 유사한 최근 Meta 토론이 있습니다:

또한, 1.182.0 이후의 aws-sdk-s3 변경 로그 항목이 관련 있어 보입니다:

  • 1.201.0: when_required 모드에서 request_checksum_calculation을 준수하도록 멀티파트 업로드 수정
  • 1.210.2: PutObject 및 UploadPart 작업에서 사용자 정의 엔드포인트 또는 엔드포인트 제공자를 사용할 때 헤더 요청 체크섬으로 폴백

Discourse main은 현재 여전히 aws-sdk-s3를 1.182.0으로 고정하고 있는 것으로 보입니다:

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

오래전에 확인한 건 아니지만, 예전에 이렇게 처리했던 적이 있습니다:

이들은 이 문제를 #contribute:bug로 간주하지 않습니다. 왜냐하면 전 세계의 모든 S3 호환(이것도 좀 애매한) 서비스를 지원한다고 주장하지 않기 때문입니다.

구체적으로 어떤 사이트들을 위해 이렇게 했는지 기억이 나지 않지만, 최근에 이 부분에 대해 변경한 것이 없었던 것 같아서 이것이 여전히 "최선"의 우회 방법이라고 생각합니다.

AWS가 새로운 라이브러리를 출시했을 때 다른 서비스 제공업체들의 서비스들을 망가뜨렸다는 내용으로 다른 주제들 몇 개가 있었던 것 같습니다.

2개의 좋아요

감사합니다. 저에게는 이 방법으로 문제가 해결되었습니다.

app.yml에서 after_bundle_exec를 통해 워크어라운드를 직접 적용하고, aws-sdk-s31.177.0으로, aws-sdk-core3.215로 고정시킨 후 컨테이너를 다시 빌드했습니다. 이후 Cloudflare R2로의 수동 백업이 다시 성공했으며, 이전에 실패하던 브라우저 업로드도 다시 정상 작동하기 시작했습니다.

제 경우에는 aws-sdk-s3 1.182.0에서 multipart upload failed: undefined method 'downcase' for nil 오류로 나타났습니다.

워크어라운드 감사합니다.

1개의 좋아요

수정… 이 우회 방법이 저한테도 효과가 있었어요. 다만 기존 훅 블록에 추가하는 대신 별도의 hooks: 블록에 넣어야 했어요. 제가 너무 멍청했네요.

1개의 좋아요