antiwork/gumroad · error · Link::LinkInvalid
You must connect at least one payment method before you can
Error message
You must connect at least one payment method before you can publish this product for sale.
What it means
Raised as Link::LinkInvalid by Link#enforce_merchant_account_exits_for_new_users! when publishing while publishable? (delegates to user.can_publish_products?, app/models/link.rb:602) is false and no payout-setup rejection note exists. The message comes from publish_blocked_message, which returns this generic variant when user.latest_payout_setup_rejection_note is blank — i.e. the seller simply has no connected payout rail yet.
Source
Thrown at app/models/link.rb:1679
return if user.confirmed?
errors.add(:base, "You have to confirm your email address before you can do that.")
raise LinkInvalid, "You have to confirm your email address before you can do that."
end
def enforce_shipping_destinations_presence!
return unless is_physical
return if shipping_destinations.alive.present?
errors.add(:base, "The product needs to be shippable to at least one destination.")
raise LinkInvalid, "The product needs to be shippable to at least one destination."
end
def enforce_merchant_account_exits_for_new_users!
return if publishable?
errors.add(:base, publish_blocked_message)
raise LinkInvalid, publish_blocked_message
end
# A seller whose payout setup Stripe rejected has a saved bank account and no rail, so telling
# them to connect a payment method sends them looking for something that is already there. Point
# at the rejection instead — the seller-visible note recorded when Stripe refused the account
# (gumroad-private#1777).
#
# Keyed on the note's own marker rather than on the newest seller-visible payout note, which is
# usually an unrelated skipped-payout explanation.
def publish_blocked_message
rejection = user.latest_payout_setup_rejection_note
return "You must connect at least one payment method before you can publish this product for sale." if rejection.blank?
"Your payout setup hasn't gone through yet, so you can't publish this product for sale. #{rejection.content}"
end
def free_trial_only_enabled_if_recurring_billing
if !is_recurring_billing && (free_trial_enabled? || free_trial_duration_unit.present? || free_trial_duration_amount.present?)View on GitHub (pinned to afeacbd394)
Solutions
- Complete payout setup (connect a payment method / Stripe account) in settings, confirm user.can_publish_products? becomes true, then publish.
- Gate the Publish action on user.can_publish_products? so sellers are routed to payouts onboarding first.
- Rescue Link::LinkInvalid and show errors.full_messages.
Example fix
# before
link.publish! # LinkInvalid: must connect a payment method
# after
unless link.user.can_publish_products?
return { error: "You must connect at least one payment method before you can publish this product for sale." }
end
link.publish! Defensive patterns
Strategy: validation
Validate before calling
return { error: 'Connect a payment method first.' } unless link.user.can_publish_products? Try / catch
begin
link.publish!
rescue Link::LinkInvalid
render json: { errors: link.errors.full_messages }, status: :unprocessable_entity
end Prevention
- Gate publishing on user.can_publish_products? (what publishable? delegates to).
- Send sellers through payouts onboarding before the product form.
- After connecting a method, verify the flag flips before retrying publish.
When it happens
Trigger: Publishing a product as a seller who has not connected any payment/payout method (no merchant account usable for charges), with no recorded Stripe payout-setup rejection.
Common situations: New sellers skipping the payouts onboarding step and going straight to publishing; disconnected/removed all payout accounts; sandbox accounts without connected Stripe.
Related errors
- Your payout setup hasn't gone through yet, so you can't publ
- This product was unpublished by Gumroad and cannot be republ
- You have to confirm your email address before you can do tha
- Sorry, shipping destinations have to be unique.
- The product needs to be shippable to at least one destinatio
AI-assisted analysis of antiwork/gumroad@afeacbd394 (2026-08-21).
Data as JSON: /api/errors/96d49c17793aecde.
Report an issue: GitHub.