carrierwaveuploader/carrierwave · error · NotImplementedError
Need to implement #cache! if you want to use #{self.class.na
Error message
Need to implement #cache! if you want to use #{self.class.name} as a cache storage. What it means
NotImplementedError raised by the cache! stub on CarrierWave::Storage::Abstract. Any storage engine whose class does not override cache! (the base class only provides empty store!/retrieve! bodies) blows up the moment CarrierWave tries to write a cache file through it. Cache storage is resolved as self.class.cache_storage || self.class.storage, so a store-only engine used as cache storage hits this on every upload.
Source
Thrown at lib/carrierwave/storage/abstract.rb:27
attr_reader :uploader
def initialize(uploader)
@uploader = uploader
end
def identifier
uploader.deduplicated_filename
end
def store!(file)
end
def retrieve!(identifier)
end
def cache!(new_file)
raise NotImplementedError, "Need to implement #cache! if you want to use #{self.class.name} as a cache storage."
end
def retrieve_from_cache!(identifier)
raise NotImplementedError, "Need to implement #retrieve_from_cache! if you want to use #{self.class.name} as a cache storage."
end
def delete_dir!(path)
raise NotImplementedError, "Need to implement #delete_dir! if you want to use #{self.class.name} as a cache storage."
end
def clean_cache!(seconds)
raise NotImplementedError, "Need to implement #clean_cache! if you want to use #{self.class.name} as a cache storage."
end
end # Abstract
end # Storage
end # CarrierWave
View on GitHub (pinned to b5f0abe10e)
Solutions
- Set config.cache_storage = :file so uploads cache on local disk and only final storage uses your engine
- Implement #cache! (alongside retrieve_from_cache!, delete_dir!, clean_cache!) in your CarrierWave::Storage::Abstract subclass
- If using fog and hitting this, upgrade CarrierWave — its Fog storage implements the cache interface
Example fix
# before
class Storage::MyDb < CarrierWave::Storage::Abstract
def store!(file); ...; end
end
CarrierWave.configure { |c| c.storage = :my_db } # cache! NotImplementedError on upload
# after
CarrierWave.configure do |c|
c.storage = :my_db
c.cache_storage = :file # cache locally, store remotely
end Defensive patterns
Strategy: validation
Validate before calling
# fail fast at boot instead of on first upload
cache_engine = (MyUploader.cache_storage || MyUploader.storage)
unless cache_engine.instance_methods.include?(:cache!)
raise "#{cache_engine} cannot be used as cache storage: implement #cache!"
end Type guard
# for custom storage classes
def cache_capable_storage?(klass)
klass.instance_methods.include?(:cache!) &&
klass.instance_methods.include?(:retrieve_from_cache!) &&
klass.instance_methods.include?(:delete_dir!) &&
klass.instance_methods.include?(:clean_cache!)
end Prevention
- Default to config.cache_storage = :file whenever the main storage is custom or remote
- Cover all four cache interface methods (#cache!, #retrieve_from_cache!, #delete_dir!, #clean_cache!) in custom storages and their specs
- Boot-time assert the resolved cache storage responds to the full cache interface
When it happens
Trigger: Setting config.cache_storage (or storage, with cache_storage unset) to a custom engine that subclasses CarrierWave::Storage::Abstract but only implements store!/retrieve!, or using a store-only engine where CarrierWave then calls cache_storage.cache!(file) inside Uploader::Cache#cache!.
Common situations: Writing a custom database/S3-compatible storage and forgetting the cache half; on versions where :fog does not implement cache methods, config.storage = :fog without config.cache_storage = :file; test doubles standing in for storage.
Related errors
- Need to implement #retrieve_from_cache! if you want to use #
- Need to implement #delete_dir! if you want to use #{self.cla
- Need to implement #clean_cache! if you want to use #{self.cl
- invalid cache id
- invalid filename
AI-assisted analysis of carrierwaveuploader/carrierwave@b5f0abe10e (2026-08-21).
Data as JSON: /api/errors/df3d453bb4304aff.
Report an issue: GitHub.