antiwork/gumroad · warning · DisputeEvidence::MergeCustomerCommunicationFilesService::MergeError

We could not find your uploaded files. Please upload them ag

Error message

We could not find your uploaded files. Please upload them again.

What it means

Raised as `DisputeEvidence::MergeCustomerCommunicationFilesService::MergeError` in dispute_evidence_controller.rb:129-134 when `ActiveStorage::Blob.find_signed!` fails on any submitted signed blob id — `ActiveSupport::MessageVerifier::InvalidSignature` (tampered/mismatched-purpose id) or `RecordNotFound` (blob record gone). Per the code comment this means the upload expired or the seller is retrying a submission whose blobs were already consumed; it is deliberately a user-facing alert redirect, not a 500.

Source

Thrown at app/controllers/purchases/dispute_evidence_controller.rb:132

        :customer_communication_file_signed_blob_id,
        customer_communication_file_signed_blob_ids: []
      )
    end

    # Asset bundles and server code don't deploy atomically, so a seller holding the old
    # JS bundle still submits the singular param. One file — from either param shape —
    # keeps today's direct-attach behaviour, including the PNG conversion below.
    def customer_communication_file_signed_blob_ids
      signed_blob_ids = Array.wrap(dispute_evidence_params[:customer_communication_file_signed_blob_ids]).compact_blank
      signed_blob_ids.presence || Array.wrap(dispute_evidence_params[:customer_communication_file_signed_blob_id].presence)
    end

    # A signed id that no longer resolves means the upload expired or the seller is retrying a
    # submission whose blobs were already consumed — an alert, not a 500.
    def customer_communication_file_blobs
      customer_communication_file_signed_blob_ids.map { ActiveStorage::Blob.find_signed!(_1) }
    rescue ActiveSupport::MessageVerifier::InvalidSignature, ActiveRecord::RecordNotFound
      raise DisputeEvidence::MergeCustomerCommunicationFilesService::MergeError,
            "We could not find your uploaded files. Please upload them again."
    end

    def set_dispute_evidence
      disputable = @purchase.charge.presence || @purchase
      @dispute_evidence = disputable.dispute.dispute_evidence
    end

    def check_if_needs_redirect
      message = \
        if @dispute_evidence.not_seller_contacted?
          # The feature flag was not enabled when the email was sent out
          "You are not allowed to perform this action."
        elsif @dispute_evidence.resolved?
          "Additional information can no longer be submitted for this dispute."
        elsif !@dispute_evidence.accepting_evidence?
          # Window elapsed but the row is not resolved yet: FightDisputeJob is forwarding it, so
          # anything saved now would arrive too late to be part of the submission.

View on GitHub (pinned to afeacbd394)

Solutions

  1. Re-upload the files on the dispute evidence form and submit again — fresh signed ids resolve fine.
  2. Avoid double submits: after the see-other redirect, reload the page instead of re-POSTing the old form.
  3. Keep the interval between upload and submit short; don't leave the form open overnight with pre-uploaded files.
  4. If it fails immediately after a deploy, confirm secret_key_base (and any signed-id purpose settings) matches what signed the ids.

Example fix

# before — resubmitting consumed signed ids
dispute_evidence_params[:customer_communication_file_signed_blob_ids] # => blobs purged by first submit

# after — re-upload, then submit with fresh signed ids
new_blobs = files.map { ActiveStorage::Blob.create_and_upload!(io: _1, filename: _1.original_filename) }
dispute_evidence.update(customer_communication_file_signed_blob_ids: new_blobs.map(&:signed_id))
Defensive patterns

Strategy: retry

Validate before calling

# before submitting, verify every signed id still resolves
valid = signed_blob_ids.all? { ActiveStorage::Blob.find_signed(_1).present? }
submit_dispute_evidence(signed_blob_ids) if valid

Type guard

def resolvable_signed_blob_ids?(ids)
  ids.all? { ActiveStorage::Blob.find_signed(_1).present? }
end

Try / catch

begin
  update # submits evidence
rescue DisputeEvidence::MergeCustomerCommunicationFilesService::MergeError => e
  redirect_to purchase_dispute_evidence_path(@purchase_route_id), alert: e.message # "upload them again"
end

Prevention

When it happens

Trigger: Seller uploads dispute-evidence files, waits past the signed-id validity window, then submits; double-submitting the same form (first successful submission purges the input blobs at line 85, so the retry's signed ids resolve to purged blobs); a signed id generated in one environment/secret context posted to another.

Common situations: Long dispute-evidence drafting sessions before submit; browser back-button resubmits after success; deploys rotating secret_key_base (invalidating signed ids); test fixtures signing ids with the wrong secret or purpose.

Related errors


AI-assisted analysis of antiwork/gumroad@afeacbd394 (2026-08-21). Data as JSON: /api/errors/d7662a9fef85fbb5. Report an issue: GitHub.