antiwork/gumroad · error · Subscription::UpdateFailed
replacement_card.errors.messages[:base].first
Error message
replacement_card.errors.messages[:base].first
What it means
After a chargeable is built, UpdaterService calls CreditCard.create(chargeable, card_data_handling_mode, logged_in_user). CreditCard.create does not raise on failure — it returns a CreditCard whose errors are populated. When :base errors are present, the first base message is raised as Subscription::UpdateFailed and the whole update transaction rolls back. The base message is buyer-facing (typically instructing a different card).
Source
Thrown at app/services/subscription/updater_service.rb:125
end
# Update card if necessary
unless use_existing_card?
had_saved_card = subscription.credit_card.present?
# (a) Get chargeable. Return if error
error_message = get_chargeable
if error_message.present?
logger.info("SubscriptionUpdater: Error fetching chargeable for subscription #{subscription.external_id}: #{error_message}")
raise Subscription::UpdateFailed, error_message
end
# (b) Create new credit card. Return if error.
replacement_card = CreditCard.create(chargeable, card_data_handling_mode, logged_in_user)
unless replacement_card.errors.empty?
logger.info("SubscriptionUpdater: Error creating new credit card for subscription #{subscription.external_id}: #{replacement_card.errors.full_messages}")
raise Subscription::UpdateFailed, replacement_card.errors.messages[:base].first
end
if indian_card_mandate_validation_required?(replacement_card)
# A plan update builds its replacement purchase before mandate validation. Keep the
# new card available for that build, but persist it only after validation succeeds.
subscription.credit_card = replacement_card
else
associate_replacement_card!(replacement_card, had_saved_card:, **validate_indian_card_mandate!(replacement_card))
replacement_card = nil
end
end
if !same_plan_and_price? || (is_resubscribing && discount_changed) || seller_price_changed
self.new_purchase = subscription.update_current_plan!(
new_variants: variants,
new_price: price,
new_quantity: params[:quantity],
perceived_price_cents: purchase_perceived_price_cents(original_discount),View on GitHub (pinned to afeacbd394)
Solutions
- Read the logged line "SubscriptionUpdater: Error creating new credit card" — replacement_card.errors.full_messages names the exact base error(s).
- Retry with a freshly entered card; token reuse after a double-submit is the most common cause.
- If the base error looks like a processor/API failure rather than a card problem, verify charge processor health and credentials, then retry.
Example fix
# before: assuming CreditCard.create always succeeds card = CreditCard.create(chargeable, card_data_handling_mode, user) subscription.credit_card = card # after: mirror the service's guard (updater_service.rb:123) raise Subscription::UpdateFailed, card.errors.messages[:base].first unless card.errors.empty?
Defensive patterns
Strategy: fallback
Try / catch
begin
result = Subscription::UpdaterService.new(subscription:, params:, logged_in_user:, gumroad_guid:, remote_ip:).perform
rescue Subscription::UpdateFailed => e
result = { success: false, error_message: e.message } # keep the old card; prompt re-entry
end
render_error(result[:error_message]) unless result[:success] Prevention
- Disable the submit button after the first click — double-submits consume the token so the second create fails.
- Treat any :base error from CreditCard.create as buyer-actionable and surface it verbatim rather than retrying blindly.
- Confirm the PayPal billing agreement is fully set up before offering it as a membership payment method.
When it happens
Trigger: A new card is supplied on a membership update (use_existing_card? false) and the charge processor rejects saving the payment method: Stripe customer/card record creation fails, the instrument data in the chargeable fails CreditCard :base validations, or the token passed to card creation has already been consumed.
Common situations: Double-submit of the card form consuming the token on the first attempt, PayPal billing agreement not yet confirmed when card creation runs, charge processor outage mid-flow, or a chargeable built for a processor the merchant account no longer accepts.
Related errors
- error_message (from get_chargeable, charge-processor card er
- error_message (PayPal account unsupported / payment method n
- responseData.error_message
- responseData.error_message
- ${responseData.error}
AI-assisted analysis of antiwork/gumroad@afeacbd394 (2026-08-21).
Data as JSON: /api/errors/1cc8769791af1e6b.
Report an issue: GitHub.