Summary
When ACTIVE_STORAGE_SERVICE is set to s3, custom user avatars and account logos upload successfully but fail to render afterward.
This happens because the controllers call ActiveStorage::Blob.service.path_for(...), which works for DiskService but raises on ActiveStorage::Service::S3Service.
Reproduction
- Configure Campfire production storage to use
ACTIVE_STORAGE_SERVICE=s3.
- Point it at any S3-compatible backend.
- I reproduced this with MinIO, but this should affect any
ActiveStorage::Service::S3Service backend.
- Upload a user avatar from
/users/me/profile.
- Optionally upload an account logo as well.
Expected
The uploaded avatar/logo should render normally.
Actual
The upload succeeds, but the follow-up image request returns 500 and the UI shows a broken image.
Error
NoMethodError (undefined method 'path_for' for an instance of ActiveStorage::Service::S3Service)
Affected code paths on main:
app/controllers/users/avatars_controller.rb
app/controllers/accounts/logos_controller.rb
Notes
In my reproduction, the blob upload and subsequent download both succeeded. The failure happens only when the controller tries to serve the processed variant back using the disk-only path_for API.
The fix was to stream the processed representation through Active Storage instead of reading it via path_for.
Summary
When
ACTIVE_STORAGE_SERVICEis set tos3, custom user avatars and account logos upload successfully but fail to render afterward.This happens because the controllers call
ActiveStorage::Blob.service.path_for(...), which works forDiskServicebut raises onActiveStorage::Service::S3Service.Reproduction
ACTIVE_STORAGE_SERVICE=s3.ActiveStorage::Service::S3Servicebackend./users/me/profile.Expected
The uploaded avatar/logo should render normally.
Actual
The upload succeeds, but the follow-up image request returns
500and the UI shows a broken image.Error
Affected code paths on
main:app/controllers/users/avatars_controller.rbapp/controllers/accounts/logos_controller.rbNotes
In my reproduction, the blob upload and subsequent download both succeeded. The failure happens only when the controller tries to serve the processed variant back using the disk-only
path_forAPI.The fix was to stream the processed representation through Active Storage instead of reading it via
path_for.