carrierwaveuploader/carrierwave · error · CarrierWave::DownloadError
could not download file: #{e.message}
Error message
could not download file: #{e.message} What it means
Raised as CarrierWave::DownloadError by CarrierWave::Downloader::Base#download! when the underlying Net::HTTP request to a remote URL fails for any reason (DNS failure, timeout, SSL error, or a non-2xx HTTP status, which response.value turns into an error). The downloader retries the request up to uploader.download_retry_count times (default 0) waiting download_retry_wait_time seconds (default 5) between attempts, then gives up and wraps the last exception message in this error.
Source
Thrown at lib/carrierwave/downloader/base.rb:53
if ::SsrfFilter::VERSION.to_f < 1.1
response = SsrfFilter.get(uri, headers: headers) do |req|
request = req
end
else
response = SsrfFilter.get(uri, headers: headers, request_proc: ->(req) { request = req }) do |res|
res.body # ensure to read body
end
end
response.uri = request.uri
response.value
end
rescue StandardError => e
if @current_download_retry_count < @uploader.download_retry_count
@current_download_retry_count += 1
sleep @uploader.download_retry_wait_time
retry
else
raise CarrierWave::DownloadError, "could not download file: #{e.message}"
end
end
CarrierWave::Downloader::RemoteFile.new(response)
end
##
# Processes the given URL by parsing it, and escaping if necessary. Public to allow overriding.
#
# === Parameters
#
# [url (String)] The URL where the remote file is stored
#
def process_uri(source)
uri = Addressable::URI.parse(source)
uri.host = uri.normalized_host
# Perform decode first, as the path is likely to be already encoded
uri.path = encode_path(decode_uri(uri.path)) if uri.path =~ CarrierWave::Utilities::Uri::PATH_UNSAFE
uri.query = encode_non_ascii(uri.query) if uri.queryView on GitHub (pinned to b5f0abe10e)
Solutions
- Verify the URL actually returns the file with 2xx status (curl -I <url>) and fix or reject it
- Rescue CarrierWave::DownloadError where you assign the remote URL and show a friendly validation message
- Enable retries in an initializer: config.download_retry_count = 3 and config.download_retry_wait_time = 5
- For persistent failures, check DNS/firewall/proxy egress rules and TLS certificate validity from the app host
Example fix
# before user.avatar = params[:avatar_url] # raises CarrierWave::DownloadError on bad URL # after begin user.avatar = params[:avatar_url] rescue CarrierWave::DownloadError => e user.errors.add(:avatar_url, e.message) end
Defensive patterns
Strategy: try-catch
Validate before calling
require 'net/http'
def downloadable?(url, timeout: 5)
uri = URI.parse(url)
return false unless uri.is_a?(URI::HTTP)
res = Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == 'https', open_timeout: timeout, read_timeout: timeout) { |http| http.head(uri.request_uri) }
res.is_a?(Net::HTTPSuccess) && (res['content-length'].nil? || res['content-length'].to_i > 0)
rescue StandardError
false
end
return unless downloadable?(params[:avatar_url]) Try / catch
begin record.avatar = params[:avatar_url] # or uploader.download!(url) rescue CarrierWave::DownloadError => e record.errors.add(:avatar_url, :download_failed, message: e.message) end
Prevention
- Wrap every remote-URL assignment in rescue CarrierWave::DownloadError and map it to a form error
- Configure config.download_retry_count and download_retry_wait_time for transient network resilience instead of the 0-retry default
- Preflight user-supplied URLs with a HEAD request (status + content-length) before storing them
When it happens
Trigger: Calling uploader.download!('http://...') or assigning a remote URL attribute (e.g. user.avatar = 'http://example.com/photo.jpg' with remote_avatar_url form fields) where the host is unreachable, the URL returns 404/500 (response.value raises on non-2xx), the TLS certificate is invalid, or the connection times out after the retry budget is exhausted.
Common situations: Apps that let users upload 'avatar by URL'; the linked server is down or blocks the request; a redirect chain ends in an error; using default config.download_retry_count = 0 so even one transient network hiccup surfaces as this error.
Related errors
- could not download file: No Content
- couldn't parse URL: #{source}
- errors.messages.processing_error
- errors.messages.processing_error
- errors.messages.processing_error
AI-assisted analysis of carrierwaveuploader/carrierwave@b5f0abe10e (2026-08-21).
Data as JSON: /api/errors/3b071ceefca402a2.
Report an issue: GitHub.