antiwork/gumroad · error · Purchase::PurchaseInvalid
Please select a start time.
Error message
Please select a start time.
What it means
For call-type products (native_type == Link::NATIVE_TYPE_CALL), checkout requires a schedulable slot: Time.zone.parse(params[:call_start_time]) must yield a time and the first variant attribute must define duration_in_minutes so end_time can be computed. A missing, blank, or unparseable start time - or a variant without a duration - raises 'Please select a start time.'
Source
Thrown at app/services/purchase/create_service.rb:467
if variant.present?
purchase.variant_attributes << variant
else
purchase.errors.add(:base, "The product's variants have changed, please refresh the page!")
raise Purchase::PurchaseInvalid, "The product's variants have changed, please refresh the page!"
end
end
elsif product.is_tiered_membership
purchase.variant_attributes << product.tiers.first
elsif product.is_physical && product.skus.is_default_sku.present?
purchase.variant_attributes << product.skus.is_default_sku.first
end
if product.native_type == Link::NATIVE_TYPE_CALL
start_time = Time.zone.parse(params[:call_start_time] || "")
duration_in_minutes = purchase.variant_attributes.first&.duration_in_minutes
if start_time.blank? || duration_in_minutes.blank?
raise Purchase::PurchaseInvalid, "Please select a start time."
end
end_time = start_time + duration_in_minutes.minutes
purchase.build_call(start_time:, end_time:)
end
build_custom_fields(purchase, params[:custom_fields] || [], product:)
product.bundle_products.alive.each do |bundle_product|
# Temporarily create custom fields on the bundle purchase in case it can't complete yet due to SCA.
# The custom fields will be moved to each product purchase when the receipt is generated.
custom_fields_params = params[:bundle_products]&.find { _1[:product_id] == bundle_product.product.external_id }&.dig(:custom_fields)
build_custom_fields(purchase, custom_fields_params || [], bundle_product:)
end
purchase.url_parameters = parse_url_parameters(params_for_purchase[:url_parameters])
purchase
endView on GitHub (pinned to afeacbd394)
Solutions
- Select a start time and resubmit using an ISO 8601 string with zone, e.g. 2026-08-21T15:00:00-07:00.
- Ensure the selected call variant defines duration_in_minutes.
- Integrators: require a chosen slot client-side and validate the string parses before submit.
Example fix
# before: empty/unparseable start time params[:call_start_time] = '' # after: send an ISO 8601 timestamp with an explicit offset params[:call_start_time] = '2026-08-21T15:00:00-07:00'
Defensive patterns
Strategy: validation
Validate before calling
if product.native_type == Link::NATIVE_TYPE_CALL raise ArgumentError, 'call_start_time required' if Time.zone.parse(params[:call_start_time].to_s).blank? end
Type guard
def parseable_start_time?(value) Time.zone.parse(value.to_s).present? end
Try / catch
begin Purchase::CreateService.new(product:, params:, buyer:).perform rescue Purchase::PurchaseInvalid => e # require the buyer to pick a slot; no automated recovery render_checkout_error(e.message) if e.message == 'Please select a start time.' end
Prevention
- Require a selected slot client-side before enabling submit.
- Send start times as ISO 8601 strings with an explicit zone offset.
- Verify the selected call variant defines duration_in_minutes before checkout.
When it happens
Trigger: product.native_type == Link::NATIVE_TYPE_CALL with params[:call_start_time] missing, empty, or in a format Time.zone.parse rejects (returns nil), OR purchase.variant_attributes.first.duration_in_minutes blank.
Common situations: Buyer never picked a slot and the client submitted anyway; datetime string without a parseable format or zone; call product whose selected variant/tier lacks duration configuration.
Related errors
- The cart does not have any products to which the upsell appl
- Tip is not allowed for this product
- Tip is too large for this purchase
- 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/bc640ca6abd59160.
Report an issue: GitHub.