antiwork/gumroad · error · Link::LinkInvalid

The suggested price you entered was too low.

Error message

The suggested price you entered was too low.

What it means

For a pay-what-you-want tier, each recurrence's entry is checked: if suggested_price_cents is present and price_cents (the tier's price for that recurrence) is greater than it, the suggestion sits below the tier's own price, so the save fails with Link::LinkInvalid. The suggested amount must be at least the tier price for that recurrence.

Source

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

    # 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."
        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|

View on GitHub (pinned to afeacbd394)

Solutions

  1. Raise the suggested price to at least the tier's price for that recurrence
  2. Or lower the tier's price (price_cents) to or below the suggested price
  3. Double-check both fields are in cents and belong to the same recurrence (monthly vs yearly mix-ups are common)

Example fix

# before
{ price_cents: 1000, suggested_price_cents: 500 } # $10 tier, $5 suggestion
# => Link::LinkInvalid: The suggested price you entered was too low.

# after
{ price_cents: 1000, suggested_price_cents: 1500 } # $10 tier, $15 suggestion
Defensive patterns

Strategy: validation

Validate before calling

variant_params[:recurrence_price_values].each do |recurrence, info|
  next unless info[:suggested_price_cents].present?
  if info[:price_cents].to_i > info[:suggested_price_cents].to_i
    raise "suggested price for #{recurrence} is below the tier price"
  end
end

Try / catch

begin
  VariantCategoryUpdaterService.new(product:, category_params:).process
rescue Link::LinkInvalid
  render_edit_form_with(product.errors.full_messages)
end

Prevention

When it happens

Trigger: A tier priced at $10/month whose suggested price for 'monthly' is set to $5 — price_cents (1000) > suggested_price_cents (500) trips the raise.

Common situations: Editors entering the suggestion in the wrong field or the wrong unit (dollars vs cents), or lowering a tier's base price assumption after suggestions were already set.

Related errors


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