{"record":{"id":"c6b1d66bcb9f7d4c","repo":"antiwork/gumroad","slug":"tip-is-not-allowed-for-this-product","errorCode":null,"errorMessage":"Tip is not allowed for this product","messagePattern":"Tip is not allowed for this product","errorType":"exception","errorClass":"Purchase::PurchaseInvalid","httpStatus":null,"severity":"error","filePath":"app/services/purchase/create_service.rb","lineNumber":144,"sourceCode":"          if purchase.offer_code.blank? && upsell.offer_code&.evaluate_for_buyer(buyer, product: purchase.link).present? &&\n             (!params[:is_purchasing_power_parity_discounted] || perceived_price_matches_accepted_offer?(upsell.offer_code))\n            purchase.offer_code = upsell.offer_code\n          end\n        end\n        purchase.build_upsell_purchase(\n          upsell:,\n          selected_product: Link.find_by_external_id(params[:accepted_offer][:original_product_id]),\n          upsell_variant: params[:accepted_offer][:original_variant_id].present? ?\n            upsell.upsell_variants.alive.find_by(\n              selected_variant: BaseVariant.find_by_external_id(params[:accepted_offer][:original_variant_id])\n            ) :\n            nil\n        )\n        raise Purchase::PurchaseInvalid, purchase.upsell_purchase.errors.first.message unless purchase.upsell_purchase.valid?\n      end\n\n      if params[:tip_cents].present? && params[:tip_cents] > 0\n        raise Purchase::PurchaseInvalid, \"Tip is not allowed for this product\" unless purchase.seller.tipping_enabled? && product.not_is_tiered_membership?\n\n        raise Purchase::PurchaseInvalid, \"Tip is too large for this purchase\" if (purchase_params[:perceived_price_cents].ceil - params[:tip_cents].floor) < purchase.minimum_paid_price_cents\n\n        purchase.build_tip(value_cents: params[:tip_cents], value_usd_cents: get_usd_cents(product.price_currency_type, params[:tip_cents]))\n      end\n\n      validate_bundle_products\n\n      purchase.prepare_for_charge!(locked_rate: buyer_currency_quote_rate_hint(purchase))\n\n      purchase.build_purchase_wallet_type(wallet_type: params[:wallet_type]) if params[:wallet_type].present?\n\n      payment_flow_attributes = PurchasePaymentFlow.attributes_for_checkout_params(params)\n      # The purchase may still be unsaved here: `prepare_for_charge!` leaves it\n      # unpersisted when a validation fails (for example, an invalid email).\n      # Creating the dependent analytics row on an unsaved parent raises\n      # ActiveRecord::RecordNotSaved, and a purchase that never saved has no\n      # payment flow worth recording anyway.","sourceCodeStart":126,"sourceCodeEnd":162,"githubUrl":"https://github.com/antiwork/gumroad/blob/afeacbd394069a1cbf0c6c50ee8e900925050370/app/services/purchase/create_service.rb#L126-L162","documentation":"Raised when the checkout submits a positive tip (params[:tip_cents] present and > 0) on a purchase that cannot accept one: either the seller has not enabled tipping (seller.tipping_enabled?, a per-seller checkout setting) or the product is a tiered membership (product.not_is_tiered_membership? is false). It stops Gumroad from collecting a tip the seller/product does not support.","triggerScenarios":"params[:tip_cents] > 0 together with purchase.seller.tipping_enabled? == false, OR product.is_tiered_membership? == true, in the same Purchase::CreateService#perform call.","commonSituations":"A custom or embedded checkout that always includes tip_cents; a buyer holding a stale page open while the seller turns tipping off; tipping UI incorrectly rendered on membership-tier products.","solutions":["Do not send tip_cents (or send 0) for this checkout.","Seller: enable tipping in checkout settings if tips should be collected.","Integrators: render the tip input only when seller.tipping_enabled? is true and the product is not a tiered membership."],"exampleFix":"# before: tip submitted unconditionally\nparams[:tip_cents] = 200\n\n# after: tip only when the purchase allows it\nparams[:tip_cents] = (seller.tipping_enabled? && !product.is_tiered_membership?) ? 200 : 0","handlingStrategy":"validation","validationCode":"tip_allowed = seller.tipping_enabled? && product.not_is_tiered_membership?\nparams[:tip_cents] = 0 if params[:tip_cents].to_i > 0 && !tip_allowed","typeGuard":"def tip_allowed?(seller, product)\n  seller.tipping_enabled? && product.not_is_tiered_membership?\nend","tryCatchPattern":"begin\n  Purchase::CreateService.new(product:, params:, buyer:).perform\nrescue Purchase::PurchaseInvalid => e\n  if e.message == 'Tip is not allowed for this product'\n    params[:tip_cents] = 0 # resubmit without the tip\n  end\nend","preventionTips":["Gate the tip UI on seller.tipping_enabled? and product.not_is_tiered_membership?.","Re-check tipping capability at submit time, not only at page load, to cover sellers toggling the setting mid-session."],"tags":["tipping","checkout","seller-settings","tiered-membership","gumroad"],"backgroundTag":"tip-not-allowed","analyzedSha":"afeacbd394069a1cbf0c6c50ee8e900925050370","analyzedAt":"2026-08-21T17:58:52.159Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}