carrierwaveuploader/carrierwave · error · ArgumentError
Version #{version} doesn't exist!
Error message
Version #{version} doesn't exist! What it means
`uploader.url(:version_name)` proxies to the named version: the first argument is treated as a version name whenever it responds to `to_sym` (Symbols and Strings both do). If `versions[version.to_sym]` is nil — i.e. that version was never declared with a `version :name do ... end` block in the uploader — an ArgumentError "Version X doesn't exist!" is raised before any URL is built. Versions disabled at runtime by `:if`/`:unless` conditions are still present in the `versions` hash, so this error specifically means the version is not defined on the class, not merely inactive.
Source
Thrown at lib/carrierwave/uploader/versions.rb:265
# my_uploader.url # => /path/to/my/uploader.gif
# my_uploader.url(:thumb) # => /path/to/my/thumb_uploader.gif
# my_uploader.url(:thumb, :small) # => /path/to/my/thumb_small_uploader.gif
# my_uploader.url(:query => {"response-content-disposition" => "attachment"})
# my_uploader.url(:version, :sub_version, :query => {"response-content-disposition" => "attachment"})
#
# === Parameters
#
# [*args (Symbol)] any number of versions
# OR/AND
# [Hash] query params
#
# === Returns
#
# [String] the location where this file is accessible via a url
#
def url(*args)
if (version = args.first) && version.respond_to?(:to_sym)
raise ArgumentError, "Version #{version} doesn't exist!" if versions[version.to_sym].nil?
# recursively proxy to version
versions[version.to_sym].url(*args[1..-1])
elsif args.first
super(args.first)
else
super
end
end
##
# Recreate versions and reprocess them. This can be used to recreate
# versions if their parameters somehow have changed.
#
def recreate_versions!(*names)
# As well as specified versions, we need to reprocess versions
# that are the source of another version.
self.cache_id = CarrierWave.generate_cache_idView on GitHub (pinned to b5f0abe10e)
Solutions
- Declare the missing version in the uploader: `version :thumb do process resize_to_limit: [200, 200] end`.
- Fix the name at the call site to match the declared symbol exactly (check with `uploader.versions.keys.inspect`).
- Guard the call: `user.avatar.url(:thumb) if user.avatar.versions.key?(:thumb)`.
- Never pass user input straight into `url`; map permitted style names through an allowlist hash first.
Example fix
# before
# view: <%= image_tag user.avatar.url(:thumb) %>
class AvatarUploader < CarrierWave::Uploader::Base
# no version :thumb declared
end
# => ArgumentError: Version thumb doesn't exist!
# after
class AvatarUploader < CarrierWave::Uploader::Base
include CarrierWave::MiniMagick
version :thumb do
process resize_to_limit: [200, 200]
end
end Defensive patterns
Strategy: validation
Validate before calling
def version_url(uploader, name) name = name.to_sym return nil unless uploader.versions.key?(name) # same lookup url() performs uploader.url(name) end
Type guard
def version_defined?(uploader, name) name.respond_to?(:to_sym) && uploader.versions.key?(name.to_sym) end
Try / catch
begin url = user.avatar.url(:thumb) rescue ArgumentError => e raise unless e.message =~ /Version .+ doesn't exist!/ url = user.avatar.url # fall back to the original file end
Prevention
- Define versions in a shared base uploader or concern when many uploaders must expose the same names.
- Never feed params straight into url(); map user input through an allowlist of style names first.
- Assert version names in a view spec/helper test (assert image_tag renders) so renames break CI, not production.
- Remember a String first argument is also treated as a version name — pass query params as a Hash (e.g. url(query: {...})).
When it happens
Trigger: Calling `user.avatar.url(:thumb)` when AvatarUploader declares no `version :thumb`; a typo or wrong name (`:thumbnail` vs `:thumb`); passing a String first argument (`url('thumb')`) — it responds to `to_sym` so it is looked up as a version, not a query; passing nested version names in the wrong order (`url(:small, :thumb)` when the uploader nests `:small` inside `:thumb`); view code shared across uploaders where only some define the version.
Common situations: Copy-pasted views referencing a version that a particular uploader doesn't define; renaming or removing a version without sweeping views/helpers; consuming `url(params[:style])` with user-supplied style names; code assuming a version exists on the base class when it is defined only in a subclass or conditionally via `version :x, if: ...` (those are fine here — the hash still contains them).
Related errors
- errors.messages.extension_allowlist_error
- errors.messages.extension_denylist_error
- errors.messages.min_size_error
- errors.messages.max_size_error
- couldn't parse URL: #{source}
AI-assisted analysis of carrierwaveuploader/carrierwave@b5f0abe10e (2026-08-21).
Data as JSON: /api/errors/eed529dde8284999.
Report an issue: GitHub.