{"record":{"id":"e2fca76557266397","repo":"antiwork/gumroad","slug":"the-combined-size-of-the-uploaded-files-exceeds-th","errorCode":null,"errorMessage":"The combined size of the uploaded files exceeds the maximum allowed, even after compression. Please remove a file or upload smaller versions.","messagePattern":"The combined size of the uploaded files exceeds the maximum allowed, even after compression\\. Please remove a file or upload smaller versions\\.","errorType":"exception","errorClass":"DisputeEvidence::MergeCustomerCommunicationFilesService::FilesTooLargeError","httpStatus":null,"severity":"error","filePath":"app/services/dispute_evidence/merge_customer_communication_files_service.rb","lineNumber":87,"sourceCode":"      downloaded_files = []\n      blobs.each do |blob|\n        tempfile = Tempfile.new([\"dispute_evidence_input\", File.extname(blob.filename.to_s)], binmode: true)\n        downloaded_files << { tempfile:, content_type: blob.content_type }\n        blob.download { |chunk| tempfile.write(chunk) }\n        tempfile.flush\n      end\n      downloaded_files\n    rescue StandardError\n      downloaded_files.each { _1[:tempfile].close! }\n      raise\n    end\n\n    def merge_within_size_budget(downloaded_files)\n      # Only image pages can shrink, so a set of PDFs already over budget can never fit and\n      # the ladder would just re-run the same merge three times with an unearned \"even after\n      # compression\" message.\n      incompressible_size = downloaded_files.sum { _1[:content_type].in?(IMAGE_CONTENT_TYPES) ? 0 : File.size(_1[:tempfile].path) }\n      raise FilesTooLargeError, FILES_TOO_LARGE_MESSAGE if incompressible_size > max_size\n\n      compressible = downloaded_files.any? { _1[:content_type].in?(IMAGE_CONTENT_TYPES) }\n      compression_steps = compressible ? IMAGE_COMPRESSION_STEPS : IMAGE_COMPRESSION_STEPS.take(1)\n\n      compression_steps.each do |compression|\n        merged_path = merge(downloaded_files, compression)\n        return merged_path if File.size(merged_path) <= max_size\n\n        File.unlink(merged_path)\n      end\n\n      raise FilesTooLargeError, FILES_TOO_LARGE_MESSAGE\n    end\n\n    def merge(downloaded_files, compression)\n      page_paths = []\n      downloaded_files.each do |downloaded_file|\n        if downloaded_file[:content_type].in?(IMAGE_CONTENT_TYPES)","sourceCodeStart":69,"sourceCodeEnd":105,"githubUrl":"https://github.com/antiwork/gumroad/blob/afeacbd394069a1cbf0c6c50ee8e900925050370/app/services/dispute_evidence/merge_customer_communication_files_service.rb#L69-L105","documentation":"merge_within_size_budget first sums the sizes of all non-image (PDF) inputs — the only compressible pages are images, so a PDF set already over budget can never fit. If that incompressible_size alone exceeds max_size it raises FilesTooLargeError immediately, deliberately skipping the compression ladder, which would otherwise re-run the identical merge three times and still fail with an unearned 'even after compression' message.","triggerScenarios":"Submitting several PDFs whose combined bytes already exceed dispute_evidence.customer_communication_file_max_size, e.g. 4 × 2 MB PDF bank-statement exports against a ~5 MB remaining Stripe budget, with no images in the set at all.","commonSituations":"Chat logs and statements exported as multiple PDFs — PDFs are carried through verbatim by the merge, so their bytes are a hard floor.","solutions":["Remove one or more PDFs from the submission","Re-export leaner PDFs (disable full-font embedding, lower embedded-image quality)","Replace wall-of-text PDFs with a JPEG screenshot of the key exchange — images can be recompressed by the merge ladder"],"exampleFix":"# before\nblobs = [pdf1, pdf2, pdf3, pdf4] # 8 MB of PDFs vs 5 MB budget\n# => FilesTooLargeError: The combined size ... even after compression.\n\n# after\nblobs = [pdf1, pdf2] # 4 MB, plus a JPG of the key chat excerpt","handlingStrategy":"validation","validationCode":"pdf_bytes = blobs.select { _1.content_type == 'application/pdf' }.sum(&:byte_size)\nraise 'PDFs alone exceed the budget' if pdf_bytes > dispute_evidence.customer_communication_file_max_size","typeGuard":"def incompressible_pdf_bytes_within?(blobs, max_size)\n  blobs.select { _1.content_type == 'application/pdf' }.sum(&: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\nend","preventionTips":["PDF inputs are carried through verbatim — only image pages can shrink, so trim PDFs first","Pre-check the sum of PDF byte sizes against the remaining budget before submit","Convert wall-of-text PDFs to JPG screenshots when every megabyte matters"],"tags":["ruby","rails","file-size","pdf","dispute-evidence"],"backgroundTag":"combined-upload-size-limit","analyzedSha":"afeacbd394069a1cbf0c6c50ee8e900925050370","analyzedAt":"2026-08-21T17:58:52.159Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}