antiwork/gumroad · error · Purchase::PurchaseInvalid
error_message (preorder.errors.full_messages[0])
Error message
error_message (preorder.errors.full_messages[0])
What it means
For a standalone pre-order (not part of a combined charge), preorder.authorize! reserves the charge; when it returns with errors and the purchase is not a test purchase, the first error message is re-raised as PurchaseInvalid. The text comes from Preorder validations - most often payment-authorization failures from the charge processor. SCA-required purchases take a different branch (scheduled FailAbandonedPurchaseWorker) instead of raising.
Source
Thrown at app/services/purchase/create_service.rb:531
end
def giftee_email
giftee_purchaser&.email || gift_params[:giftee_email]
end
def build_preorder(locked_rate: nil)
raise Purchase::PurchaseInvalid, "The product was just released. Refresh the page to purchase it." unless product.is_in_preorder_state?
self.preorder = product.preorder_link.build_preorder(purchase)
if purchase.is_part_of_combined_charge?
purchase.prepare_for_charge!(locked_rate:)
else
preorder.authorize!(locked_rate:)
error_message = preorder.errors.full_messages[0]
if purchase.is_test_purchase?
preorder.mark_test_authorization_successful!
elsif error_message.present?
raise Purchase::PurchaseInvalid, error_message
elsif purchase.requires_sca?
# Leave the preorder in `in_progress` state until the the required UI action is completed.
# Check back later to see if it has been completed. If not, transition to a failed state.
FailAbandonedPurchaseWorker.perform_in(ChargeProcessor::TIME_TO_COMPLETE_SCA, purchase.id)
else
preorder.mark_authorization_successful!
end
end
end
def set_purchaser_for(purchase, purchase_email)
if buyer.present?
purchase.purchaser = buyer unless purchase.is_gift_receiver_purchase
else
user_from_email = User.find_by(email: purchase_email)
# This limits test purchase to be done in logged out mode
if purchase.link.user != user_from_email
purchase.purchaser = user_from_emailView on GitHub (pinned to afeacbd394)
Solutions
- Read the raised message - it surfaces the underlying authorization failure reason from the preorder/charge processor.
- Retry with a valid payment method after the failure is addressed.
- Integrators: log preorder.errors.full_messages (all entries) when this raise fires to capture the complete processor response.
Defensive patterns
Strategy: try-catch
Try / catch
begin
purchase, error = Purchase::CreateService.new(product:, params:, buyer:).perform
rescue Purchase::PurchaseInvalid => e
# authorization failed: message carries the processor reason; prompt for a new payment method
Rails.logger.warn("preorder authorization failed: #{e.message}")
render_checkout_error(e.message)
end Prevention
- Validate the payment method (not expired, authorizable) before starting pre-order checkout.
- Log preorder.errors.full_messages when this raise fires - the raised string is only the first error.
- Distinguish this from the SCA branch: SCA-needed authorizations do not raise, they schedule a later completion check.
When it happens
Trigger: preorder.authorize!(locked_rate:) populates preorder.errors; purchase.is_test_purchase? is false; purchase.requires_sca? is false - so the error branch fires and preorder.errors.full_messages[0] is raised verbatim.
Common situations: Card declined at pre-order authorization; charge-processor errors (amount, currency, processing limits); authorizing against a payment method that cannot be reserved.
Related errors
- Gifting is not yet enabled for pre-orders.
- giftee_purchase.errors.full_messages[0]
- The product was just released. Refresh the page to purchase
- Something went wrong. Please refresh the page to pre-order t
- The cart does not have any products to which the upsell appl
AI-assisted analysis of antiwork/gumroad@afeacbd394 (2026-08-21).
Data as JSON: /api/errors/e4782512a29eaeaa.
Report an issue: GitHub.