{"record":{"id":"390d76c827ce231e","repo":"antiwork/gumroad","slug":"the-cart-does-not-have-any-products-to-which-the-u","errorCode":null,"errorMessage":"The cart does not have any products to which the upsell applies.","messagePattern":"The cart does not have any products to which the upsell applies\\.","errorType":"exception","errorClass":"Purchase::PurchaseInvalid","httpStatus":null,"severity":"error","filePath":"app/services/purchase/create_service.rb","lineNumber":118,"sourceCode":"        valid_items = if purchase.offer_code.universal\n          excluded_permalinks = purchase.offer_code.excluded_products.pluck(:unique_permalink)\n          valid_items.reject { excluded_permalinks.include?(_1[:permalink]) }\n        else\n          valid_items.filter { purchase.offer_code.products.find_by(unique_permalink: _1[:permalink]).present? }\n        end\n        if valid_items.map { _1[:price_cents].to_i }.sum < purchase.offer_code.minimum_amount_cents\n          raise Purchase::PurchaseInvalid, \"Sorry, you have not met the offer code's minimum amount.\"\n        end\n      end\n\n      if params[:accepted_offer].present?\n        upsell = Upsell.available_to_customers.find_by_external_id(params[:accepted_offer][:id])\n        raise Purchase::PurchaseInvalid, \"Sorry, this offer is no longer available.\" unless upsell.present?\n        if upsell.cross_sell?\n          if upsell.not_replace_selected_products?\n            cart_product_permalinks = params[:cart_items].reject { _1[:permalink] == product.unique_permalink }.map { _1[:permalink] }\n            if upsell.not_is_content_upsell? && (upsell.universal ? product.user.products : upsell.selected_products).where(unique_permalink: cart_product_permalinks).empty?\n              raise Purchase::PurchaseInvalid, \"The cart does not have any products to which the upsell applies.\"\n            end\n          end\n\n          # The original discount is retained if it is better than the upsell\n          # discount. The client can't automatically set the upsell discount\n          # because it doesn't have a \"code\". Thus, upsell discount should only\n          # be applied when the purchase does not already have a discount code.\n          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])","sourceCodeStart":100,"sourceCodeEnd":136,"githubUrl":"https://github.com/antiwork/gumroad/blob/afeacbd394069a1cbf0c6c50ee8e900925050370/app/services/purchase/create_service.rb#L100-L136","documentation":"Raised by Gumroad's Purchase::CreateService when a checkout submits params[:accepted_offer] for a cross-sell upsell that keeps (rather than replaces) the buyer's selected products, but no product remaining in the cart - excluding the product being purchased - falls inside the upsell's scope. The scope is the seller's entire catalog when the upsell is universal, otherwise its explicitly selected_products. It prevents a stale or tampered accepted offer from applying a cross-sell discount to a cart that no longer contains anything the upsell covers.","triggerScenarios":"POST checkout with params[:accepted_offer][:id] naming an Upsell that is cross_sell?, has not_replace_selected_products?, and is not a content upsell, where params[:cart_items] (minus the current product's unique_permalink) contains no permalink matching (upsell.universal ? product.user.products : upsell.selected_products).","commonSituations":"Buyer removes the only eligible product from a multi-item cart but the accepted offer captured earlier is still submitted; seller edits an upsell's selected products or universal flag while buyers sit on stale checkout pages; API integrations that replay a stored accepted_offer against a rebuilt cart.","solutions":["Reload the checkout page and re-accept the upsell so the accepted offer matches the current cart.","Before submitting, confirm the cart contains at least one other product in the upsell's scope (its selected_products, or any product by the same seller when the upsell is universal).","If you administer the seller's account, verify the cross-sell upsell's 'applies to' product selection still matches what buyers actually have in their carts."],"exampleFix":"# before: accepted_offer submitted even after the eligible item was removed from the cart\nparams[:accepted_offer] = { id: upsell.external_id } # cart no longer has any product the upsell applies to\n\n# after: submit the accepted offer only while it still applies to the cart\ncart_permalinks = cart_items.reject { _1[:permalink] == product.unique_permalink }.map { _1[:permalink] }\nscope = upsell.universal ? product.user.products : upsell.selected_products\nparams[:accepted_offer] = scope.where(unique_permalink: cart_permalinks).exists? ? { id: upsell.external_id } : nil","handlingStrategy":"validation","validationCode":"if params[:accepted_offer].present?\n  upsell = Upsell.available_to_customers.find_by_external_id(params[:accepted_offer][:id])\n  if upsell&.cross_sell? && upsell.not_replace_selected_products? && upsell.not_is_content_upsell?\n    cart_permalinks = params[:cart_items].reject { _1[:permalink] == product.unique_permalink }.map { _1[:permalink] }\n    scope = upsell.universal ? product.user.products : upsell.selected_products\n    params[:accepted_offer] = nil if scope.where(unique_permalink: cart_permalinks).empty?\n  end\nend","typeGuard":"def upsell_applies_to_cart?(upsell, cart_items, product)\n  return true unless upsell.cross_sell? && upsell.not_replace_selected_products? && upsell.not_is_content_upsell?\n  permalinks = cart_items.reject { _1[:permalink] == product.unique_permalink }.map { _1[:permalink] }\n  scope = upsell.universal ? product.user.products : upsell.selected_products\n  scope.where(unique_permalink: permalinks).exists?\nend","tryCatchPattern":"begin\n  purchase, error = Purchase::CreateService.new(product:, params:, buyer:).perform\nrescue Purchase::PurchaseInvalid => e\n  # user-facing message: revalidate upsell applicability against the current cart, then prompt refresh\n  render_checkout_error(e.message) if e.message == 'The cart does not have any products to which the upsell applies.'\nend","preventionTips":["Recompute upsell applicability whenever cart contents change instead of persisting an accepted offer across cart edits.","When sellers edit upsells, expect in-flight checkouts to fail validation; design the client to revalidate on 422 and refresh.","Treat Purchase::PurchaseInvalid messages as user-facing text and surface them on the checkout page."],"tags":["upsell","cross-sell","cart","checkout","stale-state","gumroad"],"backgroundTag":"upsell-not-applicable","analyzedSha":"afeacbd394069a1cbf0c6c50ee8e900925050370","analyzedAt":"2026-08-21T17:58:52.159Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}