How to block apply more than 1 coupon in checkout

I customize Checkout with app extension

My app only allows user to apply only 1 coupon, if user apply another coupon,
the previous coupon will be deleted. All API I am using is from Shopify, but I don’t know how, in some special way,
only 1 user can apply 2 coupons in this screen and he has 2 orders with the same coupon, the other order can’t apply 2 coupons, I created the same 2 coupons on DEV environment to test but I can’t reproduce that case.
Does anyone know or have seen this case before? Or is there a solution to debug, I spent 3 days but couldn’t reproduce and test the code but still don’t know how

Hey @nhtbao101 ,

This sounds like a rare but possible edge case—likely caused by a race condition, stale session data, or Shopify’s discount logic being bypassed before your app fully loads.

To ensure only one discount is ever active, here’s solution:

  1. Clear all existing discounts before applying a new one in your Checkout UI extension:
for (const code of checkout.discountCodes) {
  await removeDiscountCode(code.code);
}
await applyDiscountCode(newCode);
  1. Add logging/tracking in your extension to monitor when and how discount codes are applied or removed.

  2. Use Shopify webhooks (CHECKOUTS_UPDATE) to track anomalies on the backend in real time.

  3. Verify discount combination rules in the admin dashboard—some setups or customer segments might allow stacking.

  4. Force synchronous control with await to avoid race conditions when removing/applying codes.

If you want me to help debug or review your code directly, please feel free to reach out—happy to help!

Best Regards,

Rajat

Shopify Expert

Hi @nhtbao101

This is related to the settings of the coupon code

Thanks guys for read my issue, more clear about my case, I’m allow to apply 1 coupon code only, when I click button Apply, the previous coupon will be remove and new coupon will be apply. The first thing I need is reproduce that case to report with my client, because if I fix that issue with no report or not sure about that bug, i’m not sure that is solution

I tested by changing the network mode to very slow network, but in the checkout screen, after you click on the apply button, the button becomes loading state and you can’t do anything, can’t checkout, I tried with the case of opening 2 tabs on the browser but still can’t find the reason.

I saw the order details in the admin and got 2 coupons that were applied in the checkout, that means user action in the checkout, no other tools involved in calling the api

Check your useEffect cases @nhtbao101 we had something similar and had to handle it properly to prevent any race conditions.

Can’t really help much here without looking at your exact code. Also try posting on dev community forum instead as you’ll get better quality responses there instead.

Best wishes,

One angle worth checking that hasn’t been mentioned yet: the /discount/ URL path.

If the customer visited something like yourstore.com/discount/CODE1 before reaching checkout, Shopify applies that discount server-side at the session level - separate from anything your extension controls. Then when they use your extension’s UI to apply CODE2, your code runs its removal logic, but it may only be working with what’s visible in the checkout.discountCodes array at that moment. If CODE1 was injected via the discount URL before the extension initialized, there’s a window where your removal loop could miss it.

This would also explain why you can’t reproduce it in a clean dev environment - you’re probably testing by entering codes directly into the checkout field, not by pre-loading one via the URL first.

To test this specifically: open yourstore.myshopify.com/discount/CODE1 in a browser, add a product to the cart, go to checkout (CODE1 should already appear), and then try applying CODE2 through your extension. See if both codes survive after your apply logic runs.

For the order in question, check the admin order timeline - it usually records each discount application event with a timestamp. That might tell you whether the second code was added before or after your extension’s logic fired, which would at least give you something concrete to show your client.

If the combination settings in Dan’s screenshot don’t apply here and the URL approach doesn’t reproduce it either, it might genuinely be a one-off platform quirk, but the discount URL path is the most likely culprit given what you’ve described.

@nhtbao101 it’s been sometime since your post. Sometime ago Shopify added the support for functions to reject discount codes conditionally.

So potentially you could just setup a custom function with the logic you require and then use that to reject the codes conditionally.

Might be worth a shot instead of relying on extensions.

@nhtbao101 ,

if the goal is controlled promotions rather than multiple codes, then upsell/bundle deal app based discounts could be a better solution than tinkering with the checkout logic.

Could have a look at AS Quantity Break & Upsell App and see if it fits your needs.

Youc an create discounts that affect only specific products or products in specific collections, and the app works through shopify functions, so it only creates one or two discounts in your store, so your Discounts dashboard remains clean and uncluttered.