antiwork/gumroad · error · ChargeProcessorCardError
india_card_mandate_missing
india_card_mandate_missing
Error message
Your card's recurring payment authorization is not active. Please update your payment method to continue.
What it means
Raised as ChargeProcessorCardError (code india_card_mandate_missing, or india_card_mandate_inactive/pending depending on status) when an off-session charge on an Indian card has no active e-mandate to attach. Under RBI rules, card recurring payments in India require a registered e-mandate; the code maps the mandate's status ("missing"/"inactive"/"pending") to a specific PurchaseErrorCode and tells the buyer to update their payment method. It is reported to ErrorNotifier with fail_fast: true.
Source
Thrown at app/models/purchase.rb:4905
return
end
if status == "pending" && source.present?
source.mark_indian_card_mandate_registration!
CheckIndianCardMandateRegistrationJob.perform_async(source.id)
end
ErrorNotifier.notify(
"Off-session charge on an Indian card has no active e-mandate to reference",
reference: external_id,
mandate_status: status,
fail_fast: true
)
error_code = {
"missing" => PurchaseErrorCode::INDIA_CARD_MANDATE_MISSING,
"inactive" => PurchaseErrorCode::INDIA_CARD_MANDATE_INACTIVE,
"pending" => PurchaseErrorCode::INDIA_CARD_MANDATE_PENDING,
}.fetch(status)
raise ChargeProcessorCardError.new(
error_code,
"Your card's recurring payment authorization is not active. Please update your payment method to continue."
)
end
def create_charge_intent(chargeable, off_session: true)
with_charge_processor_error_handler do
amount_cents = total_transaction_cents
amount_for_gumroad_cents = total_transaction_amount_for_gumroad_cents
description = "You bought #{link.long_url}!"
mandate_options = mandate_options_for_stripe
mark_indian_card_mandate_registration! if mandate_options.present?
# Renewals and preorder releases rebill a saved card whose e-mandate (Indian cards)
# was registered at the original purchase, so a missing mandate on those charges is
# an anomaly worth reporting/failing on. First-time checkout charges can also run
# off-session (multi-seller carts) but must not be treated that way.
mandate_expected = is_a_saved_card_rebill?View on GitHub (pinned to afeacbd394)
Solutions
- Send the buyer through an on-session payment flow to re-register/refresh the e-mandate (the mandate_options path — mark_indian_card_mandate_registration! shows the registration lane) and confirm the mandate reaches active status before the next renewal.
- Check the mandate status value in the ErrorNotifier payload (reference: external_id, mandate_status:) — "pending" means wait and retry after confirmation rather than demanding a new card.
- Audit why the charge ran off-session without mandate_options_for_stripe yielding options: ensure mandate creation at first purchase succeeded for Indian cards (checkout config, currency INR, amount within mandate cap).
- Once re-registered, retry the charge; the error is specific to the saved method, not the purchase.
Example fix
// before (conceptual): renewal charges blindly
chargePurchaseOffSession(subscription.latest_purchase, savedCard)
// after: branch Indian cards through mandate verification first
if (card.isIndianCard && !card.hasActiveEMandate) {
notifyBuyerToUpdatePaymentMethod(PurchaseErrorCode.INDIA_CARD_MANDATE_MISSING)
} else {
chargePurchaseOffSession(subscription.latest_purchase, savedCard)
} Defensive patterns
Strategy: try-catch
Validate before calling
# skip off-session charge until the Indian card has an active mandate if card.india? && mandate_status != "active" route_to_on_session_mandate_confirmation(purchase) return end
Type guard
def active_india_mandate?(purchase) return true unless purchase.card_indian? %w[active].include?(purchase.saved_card_mandate_status) end
Try / catch
begin
purchase.create_charge_intent(chargeable, off_session: true)
rescue ChargeProcessorCardError => e
code = e.error_code
if [PurchaseErrorCode::INDIA_CARD_MANDATE_MISSING, PurchaseErrorCode::INDIA_CARD_MANDATE_INACTIVE, PurchaseErrorCode::INDIA_CARD_MANDATE_PENDING].include?(code)
request_buyer_mandate_reauth(purchase, code) # "pending" may just need a retry later
else
raise
end
end Prevention
- Complete e-mandate registration during the first on-session purchase for every Indian card.
- Store and monitor mandate status; schedule renewals only when status is active.
- Treat "pending" as wait-and-retry, not as a hard failure requiring a new card.
When it happens
Trigger: Calling purchase.create_charge_intent(chargeable, off_session: true) where mandate_options_for_stripe returns blank because the saved Indian card's mandate status is "missing", "inactive", or "pending" — i.e. a subscription renewal or other merchant-initiated transaction on an INR Indian card with no usable e-mandate reference (external_id).
Common situations: Buyer's bank expired or suspended the e-mandate; mandate registration never completed (AOTP flow abandoned at checkout); mandate still in "pending" confirmation when the first renewal fired; renewals attempted after RBI cap changes invalidated old mandates; cards replaced/reissued losing the mandate.
Related errors
- upi_recurring_authorization_required
- upi_recurring_authorization_required
- india_card_mandate_missing
- upi_recurring_authorization_required
- We could not verify this card for recurring payments. Please
AI-assisted analysis of antiwork/gumroad@afeacbd394 (2026-08-21).
Data as JSON: /api/errors/cefa575dac35ddd7.
Report an issue: GitHub.