antiwork/gumroad · error · Link::LinkInvalid

Please provide suggested payment options.

Error message

Please provide suggested payment options.

What it means

validate_variant_recurrences! runs for tiered membership products that use variant recurrences. A tier with customizable_price (pay-what-you-want) must also supply recurrence_price_values — the suggested price for each recurrence option; a blank/missing value adds the error to :base and raises Link::LinkInvalid, aborting the save.

Source

Thrown at app/services/product/variant_category_updater_service.rb:584

      rich_contents_to_delete.map(&:mark_deleted!)
    end

    # For tiered memberships that have per-tier pricing, validates that:
    # 1. Any tiers that have "pay-what-you-want" pricing enabled have
    # recurring price data and suggested prices are high enough
    # 2. All tiers must have pricing info for the product's default recurrence
    # 3. All tiers have the same set of recurrence options selected. (Currently
    # we do not allow, e.g., Tier 1 to have monthly & yearly plans and Tier 2
    # only to have yearly plans)
    def validate_variant_recurrences!(variants)
      return unless is_tiered_membership && has_variant_recurrences?

      variants.each_with_index do |variant, index|
        if variant[:customizable_price]
          # error if "pay what you want" enabled but missing recurrence_price_values
          if !variant[:recurrence_price_values].present?
            errors.add(:base, "Please provide suggested payment options.")
            raise Link::LinkInvalid, "Please provide suggested payment options."
          end

          # error if "pay what you want" enabled but suggested price is too low
          variant[:recurrence_price_values].each do |recurrence, price_info|
            if price_info[:suggested_price_cents].present? && (price_info[:price_cents].to_i > price_info[:suggested_price_cents].to_i)
              errors.add(:base, "The suggested price you entered was too low.")
              raise Link::LinkInvalid, "The suggested price you entered was too low."
            end
          end
        end

        # error if missing pricing info for the product's default recurrence
        if product.subscription_duration.present? && (
          !variant[:recurrence_price_values][product.subscription_duration.to_s].present? ||
          !variant[:recurrence_price_values][product.subscription_duration.to_s][:enabled]
        )
          errors.add(:base, "Please provide a price for the default payment option.")
          raise Link::LinkInvalid, "Please provide a price for the default payment option."

View on GitHub (pinned to afeacbd394)

Solutions

  1. Fill in a suggested price for every payment option of that tier (monthly/yearly as configured)
  2. Or turn off 'pay what you want' for that tier so a fixed price applies
  3. Re-save — the tier index in the error context identifies which tier is incomplete

Example fix

# before
variant_params = { customizable_price: true } # no recurrence_price_values
# => Link::LinkInvalid: Please provide suggested payment options.

# after
variant_params = {
  customizable_price: true,
  recurrence_price_values: {
    'monthly' => { enabled: true, price_cents: 500, suggested_price_cents: 1500 }
  }
}
Defensive patterns

Strategy: validation

Validate before calling

variants.each do |v|
  next unless v[:customizable_price]
  raise 'provide suggested payment options' if v[:recurrence_price_values].blank?
end

Type guard

def tier_has_suggested_prices?(variant_params)
  !variant_params[:customizable_price] || variant_params[:recurrence_price_values].present?
end

Try / catch

begin
  VariantCategoryUpdaterService.new(product:, category_params:).process
rescue Link::LinkInvalid => e
  render_edit_form_with(product.errors.full_messages) # message is already on :base
end

Prevention

When it happens

Trigger: Saving a tiered membership where a tier has 'pay what you want' enabled but the suggested prices (recurrence_price_values) were cleared or never filled in for its recurrence options.

Common situations: Toggling PWYW on an existing tier whose pricing grid was never populated; editor forms that submit the customizable_price checkbox but skip the suggestion inputs.

Understand the failure class

Background: "Missing required field" and "field is required" errors: why libraries reject payloads that omit mandatory fields — this error's family across 20 libraries.

Related errors


AI-assisted analysis of antiwork/gumroad@afeacbd394 (2026-08-21). Data as JSON: /api/errors/e5a79221baec4596. Report an issue: GitHub.