{"record":{"id":"0a194f4db2052e8f","repo":"antiwork/gumroad","slug":"one-of-the-uploaded-files-exceeds-the-maximum-size","errorCode":null,"errorMessage":"One of the uploaded files exceeds the maximum size allowed.","messagePattern":"One of the uploaded files exceeds the maximum size allowed\\.","errorType":"exception","errorClass":"DisputeEvidence::MergeCustomerCommunicationFilesService::FilesTooLargeError","httpStatus":null,"severity":"error","filePath":"app/services/dispute_evidence/merge_customer_communication_files_service.rb","lineNumber":52,"sourceCode":"  end\n\n  def initialize(blobs:, max_size:)\n    @blobs = blobs\n    @max_size = max_size\n  end\n\n  # Returns a new application/pdf ActiveStorage::Blob. The input blobs are left alone: the\n  # caller purges them once the submission has actually been persisted.\n  def perform\n    if blobs.size > DisputeEvidence::MAX_CUSTOMER_COMMUNICATION_FILES\n      raise MergeError, \"You can attach up to #{DisputeEvidence::MAX_CUSTOMER_COMMUNICATION_FILES} files.\"\n    end\n    # The merged output is always application/pdf, so the model's content-type validation never\n    # sees the inputs. Everything below hands seller-supplied bytes to ImageMagick and qpdf.\n    unless blobs.all? { _1.content_type.in?(DisputeEvidence::ALLOWED_FILE_CONTENT_TYPES) }\n      raise MergeError, UNSUPPORTED_FILE_TYPE_MESSAGE\n    end\n    raise FilesTooLargeError, FILE_TOO_LARGE_MESSAGE if blobs.any? { _1.byte_size > max_size }\n\n    downloaded_files = download_blobs\n    merged_path = merge_within_size_budget(downloaded_files)\n\n    File.open(merged_path) do |file|\n      ActiveStorage::Blob.create_and_upload!(io: file, filename: MERGED_FILENAME, content_type: \"application/pdf\")\n    end\n  ensure\n    downloaded_files&.each { _1[:tempfile].close! }\n    File.unlink(merged_path) if merged_path && File.exist?(merged_path)\n  end\n\n  private\n    attr_reader :blobs, :max_size\n\n    def download_blobs\n      downloaded_files = []\n      blobs.each do |blob|","sourceCodeStart":34,"sourceCodeEnd":70,"githubUrl":"https://github.com/antiwork/gumroad/blob/afeacbd394069a1cbf0c6c50ee8e900925050370/app/services/dispute_evidence/merge_customer_communication_files_service.rb#L34-L70","documentation":"perform raises FilesTooLargeError (a subclass of MergeError) when any single blob's byte_size exceeds max_size. max_size is dispute_evidence.customer_communication_file_max_size — the remaining Stripe combined-size budget (STRIPE_MAX_COMBINED_FILE_SIZE minus what other evidence fields already consume) — so the effective per-file ceiling can be smaller than a fixed limit and shrinks as other evidence is attached.","triggerScenarios":"One upload bigger than the currently remaining Stripe budget; a multi-MB scan submitted after other large evidence files have already claimed most of the budget.","commonSituations":"High-DPI scans of receipts/contracts, 'print-quality' PDF exports, phone photos at full resolution.","solutions":["Compress the offending file below the remaining budget (re-export the PDF with lower image quality, scan at 150–200 DPI, save photos as ~80% JPEG)","Check the sizes of all files being submitted this round, including the previously attached one","If other evidence fields are consuming the budget, trim those files too"],"exampleFix":"# before\nblobs = [pdf_blob] # 6 MB, remaining budget 5 MB\n# => FilesTooLargeError: One of the uploaded files exceeds the maximum size allowed.\n\n# after\n# re-export with compressed images -> 2.5 MB PDF\nblobs = [smaller_pdf_blob]","handlingStrategy":"validation","validationCode":"max_size = dispute_evidence.customer_communication_file_max_size # remaining Stripe budget\nraise 'file too large' if blobs.any? { _1.byte_size > max_size }","typeGuard":"def all_files_within?(blobs, max_size)\n  blobs.none? { _1.byte_size > max_size }\nend","tryCatchPattern":"begin\n  DisputeEvidence::MergeCustomerCommunicationFilesService.perform(blobs:, max_size: budget)\nrescue DisputeEvidence::MergeCustomerCommunicationFilesService::FilesTooLargeError => e\n  redirect_back alert: e.message # per-file and combined overages share this error class\nend","preventionTips":["The ceiling is the REMAINING Stripe budget, not a fixed constant — re-read customer_communication_file_max_size each submission","Show per-file size and the remaining budget in the upload UI before submit","Scan at 150–200 DPI and export PDFs with compressed images to stay well under it"],"tags":["ruby","rails","file-size","stripe","dispute-evidence"],"backgroundTag":"file-size-limit-exceeded","analyzedSha":"afeacbd394069a1cbf0c6c50ee8e900925050370","analyzedAt":"2026-08-21T17:58:52.159Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}