antiwork/gumroad · error · Purchase::PurchaseInvalid
The product was just released. Refresh the page to purchase
Error message
The product was just released. Refresh the page to purchase it.
What it means
build_preorder runs when the purchase is flagged is_preorder_authorization, but it first asserts product.is_in_preorder_state?. If the product was just released, the assertion fails and the buyer is told to refresh - the pre-order authorization path no longer applies and a normal purchase must be made instead.
Source
Thrown at app/services/purchase/create_service.rb:520
is_gift_receiver_purchase: true
)
giftee_purchase = build_purchase(giftee_purchase_params)
giftee_purchase.purchaser = giftee_purchaser
giftee_purchase.gift_received = gift
giftee_purchase.process!
raise Purchase::PurchaseInvalid, giftee_purchase.errors.full_messages[0] if giftee_purchase.errors.present?
end
def giftee_purchaser
@_giftee_purchaser ||= gift_params[:giftee_id].present? ? User.alive.find_by_external_id(gift_params[:giftee_id]) : User.alive.by_email(gift_params[:giftee_email]).last
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!
endView on GitHub (pinned to afeacbd394)
Solutions
- Refresh the page and complete a normal purchase - the release flow takes over.
- Integrators: re-check product.is_in_preorder_state? immediately before submit and switch to the normal purchase flow on mismatch.
- Handle this raise by restarting checkout, never by resubmitting identical preorder params.
Example fix
# before: preorder params submitted after release params[:purchase][:is_preorder_authorization] = true # product no longer in preorder state # after: reconcile the flag with live product state params[:purchase][:is_preorder_authorization] = product.is_in_preorder_state?
Defensive patterns
Strategy: validation
Validate before calling
params[:purchase][:is_preorder_authorization] = product.is_in_preorder_state? if params[:purchase][:is_preorder_authorization]
Type guard
def preorder_flow_current?(params, product) !params[:purchase][:is_preorder_authorization] || product.is_in_preorder_state? end
Try / catch
begin Purchase::CreateService.new(product:, params:, buyer:).perform rescue Purchase::PurchaseInvalid => e # product was released mid-checkout: restart checkout in normal purchase mode redirect_to_checkout if e.message == 'The product was just released. Refresh the page to purchase it.' end
Prevention
- Re-check product.is_in_preorder_state? immediately before submit and switch flows on mismatch.
- Treat release events as checkout-invalidating for in-flight pre-order sessions.
When it happens
Trigger: Checkout was loaded while the product was a pre-order (is_preorder_authorization true in the submitted params), but by submit time product.is_in_preorder_state? is false - the classic race between release and submit. A separate guard (line 75) covers the inverse tampered case.
Common situations: Stale tabs from before a product release; integrations caching preorder state; seller releasing the product while buyers are mid-checkout.
Related errors
- The cart does not have any products to which the upsell appl
- Gifting is not yet enabled for pre-orders.
- Invalid free trial information provided. Please try again.
- The product's free trial has changed, please refresh the pag
- The bundle's contents have changed. Please refresh the page!
AI-assisted analysis of antiwork/gumroad@afeacbd394 (2026-08-21).
Data as JSON: /api/errors/74f56180218fc251.
Report an issue: GitHub.