We are experiencing an inconsistent behavior with the useBuyerJourneyIntercept hook in our Shopify Checkout UI Extension and are seeking assistance.
We are implementing a checkout extension that uses the useBuyerJourneyIntercept to prevent users from proceeding without verifying their phone number when clicking the “Continue to shipping” button. However, we have encountered a situation where the interceptor does not consistently block the checkout progression as expected.
To separate our issue from other potential problems, we have created a minimal extension that only that uses useBuyerJourneyIntercept to block checkout progression. Our logic always returns { behavior: 'block', reason: 'Invalid' }. However, we have observed that after initially click the “Continue to shipping” and getting blocked, if we change the phone number field (which is one of the input fields) and then click outside the field (blur event) and click the “Continue to shipping” button again. the checkout proceeds despite the interceptor still returning { behavior: 'block' }. The console logs consistently show the message indicating the interceptor is running and returning the block behavior.
Here is a simplified version of our code:
import { reactExtension, useBuyerJourneyIntercept } from '@shopify/ui-extensions-react/checkout';
export default reactExtension('purchase.checkout.delivery-address.render-after', () =>
Steps to reproduce:
1. Create a new app and generate a new extension with the code above.
2. Install the extension to the checkout at the `purchase.checkout.delivery-address.render-after` target.
3. Open the checkout page, fill out all required fields including the phone number field, and click the "Continue to shipping" button.
4. You will see that you cannot proceed, and the console logs will show "interceptor always block."
5. Change the phone number.
6. Out focus the field by clicking outside it.
7. Click the "Continue to shipping" button again.
8. You will see that you can proceed to the next step despite the console logs still showing "interceptor always block," indicating the interceptor is still returning the block behavior.
Has anyone else experienced a similar issue, or can anyone provide insights into why this might be happening?
This looks like a genuine platform-level bug rather than something wrong with your implementation. The fact that your console logs confirm the interceptor is still executing and returning { behavior: 'block' } - yet the checkout proceeds anyway - rules out a logic error on your end.
Here’s what’s likely happening: when the phone number field loses focus (blur), Shopify’s checkout internally re-validates its own form fields. If that internal validation passes (i.e., the field format looks valid to Shopify), the checkout engine can set an internal ““step completeable”” flag. On the next button click, there seems to be a race or ordering issue where that pre-computed internal state takes precedence over the interceptor’s return value, even though the interceptor still runs.
This behavior has been observed specifically on targets that wrap address/contact form fields because those fields have Shopify’s own built-in validation logic running in parallel with your interceptor.
A few things worth trying as workarounds:
One approach is to make your interceptor callback stable using useCallback with an explicit dependency array, even if the return value is always block. In some SDK versions, the stale closure gets de-registered silently after a field change event, and while your logs show it running, it may be a leftover reference that Shopify’s runtime is no longer honoring.
Another thing to try is forcing a re-render of the interceptor registration by tying it to a piece of state that updates on the phone field’s change event. Essentially triggering a new registration cycle after the blur.
That said, if your minimal repro truly always returns block regardless of state and the issue still reproduces, this is worth escalating directly. I’d recommend opening a ticket through the Partner Dashboard under ““Get support”” and specifically referencing the purchase.checkout.delivery-address.render-after target + blur event sequence. Shopify’s checkout extension team does monitor these - attaching your minimal repro code will help them reproduce and prioritize it.
There’s also a Checkout UI Extensions GitHub repository where this kind of platform-level inconsistency is better tracked than on the community forum. Searching for open issues around useBuyerJourneyIntercept there might surface if others have hit the same thing and found a confirmed workaround.