antiwork/gumroad · error · Link::LinkInvalid
All tiers must have the same set of payment options.
Error message
All tiers must have the same set of payment options.
What it means
The final pass of validate_variant_recurrences!: each variant's enabled recurrence keys (from recurrence_price_values, selected and sorted) are compared pairwise across tiers; the first adjacent mismatch (e.g. ['monthly','yearly'] vs ['monthly']) adds the error and raises Link::LinkInvalid. The product enforces that every tier exposes exactly the same set of payment options — mixed option sets across tiers are not representable.
Source
Thrown at app/services/product/variant_category_updater_service.rb:618
)
errors.add(:base, "Please provide a price for the default payment option.")
raise Link::LinkInvalid, "Please provide a price for the default payment option."
end
end
# error if variants have different recurrence options:
# 1. Extract variant recurrence selections:
# Ex. [["monthly", "yearly"], ["monthly"]]
enabled_recurrences_for_variants = variants.map do |variant|
variant[:recurrence_price_values].select { |k, v| v[:enabled] }.keys.sort
end
# 2. Ensure that they match
# Ex. ["monthly", "yearly"] != ["monthly"] raises error
enabled_recurrences_for_variants.each_with_index do |recurrences, index|
next_recurrences = enabled_recurrences_for_variants[index + 1]
if next_recurrences && recurrences != next_recurrences
errors.add(:base, "All tiers must have the same set of payment options.")
raise Link::LinkInvalid, "All tiers must have the same set of payment options."
end
end
end
end
View on GitHub (pinned to afeacbd394)
Solutions
- Open each tier's pricing grid and check exactly the same recurrence options on all tiers
- Or disable the extra option on every tier so the sets match
- Re-save after aligning; the pairwise comparison reports the first mismatched pair, but auditing all tiers at once is faster
Example fix
# before
tier1_recurrences = { 'monthly' => {...}, 'yearly' => {...} }
tier2_recurrences = { 'yearly' => {...} } # mismatch
# => Link::LinkInvalid: All tiers must have the same set of payment options.
# after
tier2_recurrences = { 'monthly' => {...}, 'yearly' => {...} } # same enabled set Defensive patterns
Strategy: validation
Validate before calling
enabled_sets = variants.map { |v| v[:recurrence_price_values].select { |_k, val| val[:enabled] }.keys.sort }
raise 'tiers have different payment options' unless enabled_sets.uniq.one? Type guard
def all_tiers_same_recurrence_options?(variants)
variants.map { |v| v[:recurrence_price_values].select { |_k, val| val[:enabled] }.keys.sort }.uniq.one?
end Try / catch
begin VariantCategoryUpdaterService.new(product:, category_params:).process rescue Link::LinkInvalid render_edit_form_with(product.errors.full_messages) end
Prevention
- Make the recurrence checkboxes shared across tiers in the editor so they cannot diverge
- After adding a new tier, copy the payment-option set from an existing tier before pricing it
- The server compares the sorted enabled-key SETS — a tier enabling an extra option fails even if all its prices are valid
When it happens
Trigger: Tier 1 enables monthly+yearly while Tier 2 enables only yearly; any tier disabling an option that the others keep enabled.
Common situations: Adding a new tier later and forgetting to check both periods; toggling one period off on a single tier in the editor grid.
Related errors
- Please provide suggested payment options.
- The suggested price you entered was too low.
- Please provide a price for the default payment option.
- Sorry, the price entered is too large.
- Message is required
AI-assisted analysis of antiwork/gumroad@afeacbd394 (2026-08-21).
Data as JSON: /api/errors/1ea8b219d6703129.
Report an issue: GitHub.