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

  1. Set config.cache_storage = :file so uploads cache on local disk and only final storage uses your engine
  2. Implement #cache! (alongside retrieve_from_cache!, delete_dir!, clean_cache!) in your CarrierWave::Storage::Abstract subclass
  3. 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

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


AI-assisted analysis of carrierwaveuploader/carrierwave@b5f0abe10e (2026-08-21). Data as JSON: /api/errors/df3d453bb4304aff. Report an issue: GitHub.