S3 스토리지 활성화 시 아바타 업로드 실패 (파일 존재에도 계속 오류)

Hi all,

I’m facing a strange issue with Discourse + S3 storage.

When uploading avatars, I get an error like the one below — even though the file does exist on the S3 bucket and is accessible via a valid s3_cdn_url.

Uploads for posts and attachments work perfectly. The only thing that fails is user avatar uploads.


:fire: Error message from gig.ovh/logs


Message (2 copies reported)

Could not find file in the store located at url: //gig.s3.ru-1.storage.selcloud.ru/original/1X/fd42dfa3362b66090450f2ae40f0917193fcd355.jpeg

Backtrace

/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activesupport-7.2.2.1/lib/active\_support/broadcast\_logger.rb:134\:in `block in error'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activesupport-7.2.2.1/lib/active_support/broadcast_logger.rb:231:in `block in dispatch'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activesupport-7.2.2.1/lib/active\_support/broadcast\_logger.rb:231\:in `each'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activesupport-7.2.2.1/lib/active_support/broadcast_logger.rb:231:in `dispatch'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activesupport-7.2.2.1/lib/active\_support/broadcast\_logger.rb:134\:in `error'
/var/www/discourse/app/models/optimized_image.rb:91:in `block in create\_for'
/var/www/discourse/app/models/optimized\_image.rb:19\:in `block (2 levels) in lock'
/var/www/discourse/lib/distributed_mutex.rb:53:in `block in synchronize'
/var/www/discourse/lib/distributed\_mutex.rb:49\:in `synchronize'
/var/www/discourse/lib/distributed_mutex.rb:49:in `synchronize'
/var/www/discourse/lib/distributed\_mutex.rb:34\:in `synchronize'
/var/www/discourse/app/models/optimized_image.rb:19:in `block in lock'
/var/www/discourse/lib/distributed\_mutex.rb:53\:in `block in synchronize'
/var/www/discourse/lib/distributed_mutex.rb:49:in `synchronize'
/var/www/discourse/lib/distributed\_mutex.rb:49\:in `synchronize'
/var/www/discourse/lib/distributed_mutex.rb:34:in `synchronize'
/var/www/discourse/app/models/optimized\_image.rb:18\:in `lock'
/var/www/discourse/app/models/optimized_image.rb:83:in `create\_for'
/var/www/discourse/app/models/upload.rb:151\:in `get_optimized_image'
/var/www/discourse/app/controllers/user_avatars_controller.rb:219:in `get\_optimized\_image'
/var/www/discourse/app/controllers/user\_avatars\_controller.rb:137\:in `show_in_site'
/var/www/discourse/app/controllers/user_avatars_controller.rb:90:in `block (2 levels) in show'
/var/www/discourse/lib/hijack.rb:68\:in `instance_eval'
/var/www/discourse/lib/hijack.rb:68:in `block (2 levels) in hijack'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/i18n-1.14.7/lib/i18n.rb:353\:in `with_locale'
/var/www/discourse/lib/hijack.rb:68:in `block in hijack'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.5/lib/concurrent-ruby/concurrent/promises.rb:911\:in `callback_on_resolution'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.5/lib/concurrent-ruby/concurrent/promises.rb:797:in `call\_callback'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.5/lib/concurrent-ruby/concurrent/promises.rb:803\:in `call_callbacks'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.5/lib/concurrent-ruby/concurrent/promises.rb:692:in `resolve\_with'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.5/lib/concurrent-ruby/concurrent/promises.rb:1325\:in `resolve'
/var/www/discourse/lib/scheduler/defer.rb:125:in `block in do\_work'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/rails\_multisite-6.1.0/lib/rails\_multisite/connection\_management/null\_instance.rb:49\:in `with_connection'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/rails_multisite-6.1.0/lib/rails_multisite/connection_management.rb:21:in `with\_connection'
/var/www/discourse/lib/scheduler/defer.rb:119\:in `do_work'
/var/www/discourse/lib/scheduler/defer.rb:105:in `block (2 levels) in start\_thread'

That is an S3 URL for the container

//gig.s3.ru-1.storage.selcloud.ru/original/1X/fd42dfa3362b66090450f2ae40f0917193fcd355.jpeg

The image is available at URL:

https://s3.gig.ovh/original/1X/fd42dfa3362b66090450f2ae40f0917193fcd355.jpeg

:white_check_mark: Additional Info

  • Discourse version: (latest stable)
  • External S3-compatible storage used (enable_s3_uploads = true)
  • s3_cdn_url is correctly configured and used
  • CDN URL successfully returns the file
  • File is confirmed present at the expected S3 location
  • Other uploads (images, attachments, etc.) work fine
  • The error only occurs with user avatars

:red_question_mark:Question

What could cause Discourse to fail to retrieve the file for avatar processing while the exact file exists and is reachable via the correct CDN URL?

Is there something specific to avatar processing (like get_optimized_image) that could be misconfigured or cached incorrectly?

Any suggestions or insight would be appreciated!

Thanks :folded_hands:

안녕하세요 — 이 문제를 해결하셨나요?

저도 Discourse + S3 환경에서(아바타 파일만 해당) 정확히 같은 증상을 겪고 있습니다:
Could not find file in the store located at url: //<bucket>.s3.dualstack.<region>.amazonaws.com/original/1X/<hash>.jpeg

혹시 저와 환경이 일치하는지 확인해 보실 수 있도록 제 설정에 대한 몇 가지 세부 사항을 공유합니다:

  • enable_s3_uploads = true, 객체는 original/*optimized/* 경로에 위치해 있습니다 (uploads/default 접두어 없음)

  • CloudFront(OAC)를 통해 접근하며, 버킷 자체는 비공개로 설정되어 있습니다

  • 해당 키에 객체는 실제로 존재하며, CDN URL은 정상 작동합니다

  • 오류는 아바타 처리 시에만 발생합니다

  • (가능한 문제점) 업로드 파일이 SSE-KMS로 암호화되어 있습니다

혹시 근본 원인을 찾거나 해결 방법(정책 변경, KMS 권한, 버킷 경로 정렬 등)을 찾으셨다면 어떤 방식으로 해결하셨는지 공유해 주실 수 있을까요? 감사합니다!