antiwork/gumroad · error · Purchase::PurchaseInvalid
Purchase price is invalid. Please check the price.
Error message
Purchase price is invalid. Please check the price.
What it means
validate_perceived_price raises when perceived_price_cents falls outside Purchase::MAX_PRICE_RANGE (-2_147_483_647..2_147_483_647, the signed 32-bit integer bounds of the price column, app/models/purchase.rb:51). Values beyond that cannot be stored, so checkout aborts before the purchase is built.
Source
Thrown at app/services/purchase/create_service.rb:347
raise Purchase::PurchaseInvalid, "You can't gift your own product. To give it away for free, create a 100% off discount code under Checkout > Discounts and share the checkout link." if buyer == product.user
raise Purchase::PurchaseInvalid, "You cannot gift a product to yourself. Please try gifting to another email." if giftee_email == purchase_params[:email]
raise Purchase::PurchaseInvalid, "Gift purchases cannot be on installment plans." if params[:pay_in_installments]
if product.can_gift?
gift = product.gifts.build(giftee_email:, gift_note: gift_params[:gift_note], gifter_email: params[:purchase][:email], is_recipient_hidden: gift_params[:giftee_email].blank?)
error_message = gift.save ? nil : gift.errors.full_messages[0]
raise Purchase::PurchaseInvalid, error_message if error_message.present?
gift
else
error_message = product.user.gifting_disabled? ? "The creator has disabled gifting for their products." : "Gifting is not yet enabled for pre-orders."
raise Purchase::PurchaseInvalid, error_message
end
end
def validate_perceived_price
if purchase_params[:perceived_price_cents] && !Purchase::MAX_PRICE_RANGE.cover?(purchase_params[:perceived_price_cents])
raise Purchase::PurchaseInvalid, "Purchase price is invalid. Please check the price."
end
end
def validate_zip_code
country_code_for_validation = purchase_params[:country].presence || purchase_params[:sales_tax_country_code_election]
if purchase_params[:perceived_price_cents].to_i > 0 && country_code_for_validation == Compliance::Countries::USA.alpha2 && UsZipCodes.identify_state_code(purchase_params[:zip_code]).nil?
Rails.logger.info("Zip code #{purchase_params[:zip_code]} is invalid, customer email #{purchase_params[:email]}")
raise Purchase::PurchaseInvalid, "You entered a ZIP Code that doesn't exist within your country."
end
end
def perceived_price_matches_accepted_offer?(offer_code)
return false unless offer_code
original_offer_code = purchase.offer_code
purchase.offer_code = offer_code
purchase.minimum_paid_price_cents + params[:tip_cents].to_i == purchase_params[:perceived_price_cents].to_iView on GitHub (pinned to afeacbd394)
Solutions
- Send integer cents, converted from the decimal amount exactly once.
- Validate or clamp the client input to the int32 range before submit.
- If a legitimate charge truly exceeds the range, it exceeds what Gumroad can price - split it or contact support.
Example fix
# before: cents conversion applied twice params[:purchase][:perceived_price_cents] = (price_dollars * 100 * 100).to_i # after: convert to integer cents exactly once params[:purchase][:perceived_price_cents] = (price_dollars * 100).to_i
Defensive patterns
Strategy: validation
Validate before calling
price_cents = purchase_params[:perceived_price_cents].to_i raise ArgumentError, 'perceived_price_cents out of range' unless Purchase::MAX_PRICE_RANGE.cover?(price_cents)
Type guard
def valid_price_cents?(cents) cents.is_a?(Numeric) && Purchase::MAX_PRICE_RANGE.cover?(cents.to_i) end
Try / catch
begin Purchase::CreateService.new(product:, params:, buyer:).perform rescue Purchase::PurchaseInvalid => e # a range violation is a client bug - log it and reject, do not retry the same value report_client_bug(e.message) if e.message == 'Purchase price is invalid. Please check the price.' end
Prevention
- Convert dollars to integer cents exactly once, at the boundary.
- Bound pay-what-you-want inputs to a sane maximum well below int32.
- Never round-trip prices through floats; keep cents as integers end to end.
When it happens
Trigger: params[:purchase][:perceived_price_cents] is non-nil and outside the int32 range - typically dollars converted to cents twice, float multiplication overflow, or a tampered request probing the bounds.
Common situations: Client multiplies a dollar amount by 100 twice; price parsed as dollars in one layer and cents in another; PWYW inputs accepted without an upper bound; automated requests submitting extreme values.
Related errors
- Tip is too large for this purchase
- The cart does not have any products to which the upsell appl
- Tip is not allowed for this product
- You can't gift your own product. To give it away for free, c
- You cannot gift a product to yourself. Please try gifting to
AI-assisted analysis of antiwork/gumroad@afeacbd394 (2026-08-21).
Data as JSON: /api/errors/c7e601777a461037.
Report an issue: GitHub.