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.query

View on GitHub (pinned to b5f0abe10e)

Solutions

  1. Verify the URL actually returns the file with 2xx status (curl -I <url>) and fix or reject it
  2. Rescue CarrierWave::DownloadError where you assign the remote URL and show a friendly validation message
  3. Enable retries in an initializer: config.download_retry_count = 3 and config.download_retry_wait_time = 5
  4. 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

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


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