antiwork/gumroad · error · CreatePublicMediaService::RemoteFileTooLarge
That file is too large. Images can be up to #{MAX_IMAGE_BYTE
Error message
That file is too large. Images can be up to #{MAX_IMAGE_BYTES / 1.megabyte} MB. What it means
Before streaming any body bytes, download_blob_from_url compares the remote response's Content-Length header against MAX_IMAGE_BYTES (10 MB) and raises RemoteFileTooLarge; #process rescues it into this message. This is the fast path of the size ceiling: an oversized file is cut off before it is downloaded, instead of being fully fetched and uploaded to public storage only to be rejected afterwards.
Source
Thrown at app/services/create_public_media_service.rb:189
blob
end
# Download the remote file to a tempfile with SSRF protection and a hard size ceiling, then
# store it as a blob. The size is enforced while streaming (both via the Content-Length header
# and by counting actual bytes) so a file larger than the 10 MB image cap is cut off
# mid-download instead of being fully downloaded (and uploaded to public storage) only to be
# rejected by the size check afterwards. Mirrors the hardened fetch the product thumbnail's
# URL path already uses (Thumbnail#url=).
def download_blob_from_url
normalized_url = normalize_url(url)
uri = URI.parse(normalized_url)
raise URI::InvalidURIError, "URL '#{normalized_url}' is not a web url" unless uri.scheme.in?(%w[http https])
raise URI::InvalidURIError, "URL must include a valid host" if uri.host.blank?
tempfile = Tempfile.new(binmode: true)
begin
response = SsrfFilter.get(normalized_url) do |http_response|
raise RemoteFileTooLarge if http_response["content-length"].to_i > MAX_IMAGE_BYTES
write_file = http_response.is_a?(Net::HTTPSuccess)
received_bytes = 0
byte_limit = MAX_IMAGE_BYTES
http_response.read_body do |chunk|
received_bytes += chunk.bytesize
raise RemoteFileTooLarge if received_bytes > byte_limit
tempfile.write(chunk) if write_file
end
end
raise ActiveStorage::FileNotFoundError unless response.is_a?(Net::HTTPSuccess)
tempfile.rewind
# Sniff the real content type from the file bytes. The remote server's header is used only
# as a hint — a mislabeled or disguised file is classified by what it actually contains.
content_type = Marcel::MimeType.for(tempfile, name: filename_from(uri), declared_type: response.content_type)
tempfile.rewindView on GitHub (pinned to afeacbd394)
Solutions
- Host and submit a web-sized version of the image (resize/compress until under 10 MB)
- Use a CDN thumbnail parameter if available, e.g. '?w=2000' or '/_2000x/...' variants
- Compress locally (e.g. 'convert in.png -resize 2000x -quality 85 out.jpg') and link that file
- Or direct-upload the compressed file and pass signed_blob_id instead of url
Example fix
# before url: 'https://cdn.example.com/brand-poster.png' # Content-Length: 32 MB # => failure: That file is too large. Images can be up to 10 MB. # after url: 'https://cdn.example.com/brand-poster.png?w=2000&fm=jpg' # ~1 MB
Defensive patterns
Strategy: validation
Validate before calling
MAX_IMAGE_BYTES = 10.megabytes
# hint only: dynamic endpoints can lie or omit the header
size_hint = URI.open(url, 'r') { |f| f.meta['content-length']&.to_i }
return if size_hint && size_hint <= MAX_IMAGE_BYTES
raise 'file likely exceeds the 10 MB cap' if size_hint Prevention
- Pre-shrink images to web dimensions (<= ~2000 px, JPEG ~85%) before hosting them for landing pages
- The cap (CreatePublicMediaService::MAX_IMAGE_BYTES = 10.megabytes) applies to both the url and signed_blob_id paths
- Treat Result(success: false, error_message: 'That file is too large...') as user-facing copy and show it directly
When it happens
Trigger: Passing url pointing at a file whose server advertises Content-Length greater than 10_485_760 bytes (e.g. a 32 MB PNG or a print-resolution export) to CreatePublicMediaService with only url set (no signed_blob_id).
Common situations: Sellers link high-resolution photos or unoptimized design-tool exports hosted on their own site or CDN; images large enough for print are routinely over 10 MB.
Related errors
- We couldn't download that file, please check the URL and try
- One of the uploaded files exceeds the maximum size allowed.
- The combined size of the uploaded files exceeds the maximum
- Message is required
- You can attach up to #{DisputeEvidence::MAX_CUSTOMER_COMMUNI
AI-assisted analysis of antiwork/gumroad@afeacbd394 (2026-08-21).
Data as JSON: /api/errors/6ef7a67105868eab.
Report an issue: GitHub.