In the dev tools console I can see that “Calling setCustomer“ is printed, but “setCustomer exception caught“ isn’t. Instead of the expected error, I see this exception
load.html:10 Uncaught (in promise) Error: Customer not found - id: 1
at construct (native)
at apply (native)
at _construct (address at index.android.bundle:1:650692)
at Wrapper (address at index.android.bundle:1:650344)
at construct (native)
at _callSuper (address at index.android.bundle:1:2419705)
at POSError (address at index.android.bundle:1:2419958)
at construct (native)
at _callSuper (address at index.android.bundle:1:5672019)
at CustomerNotFoundError (address at index.android.bundle:1:5672344)
at ?anon_0_ (address at index.android.bundle:1:5658726)
at next (native)
at asyncGeneratorStep (address at index.android.bundle:1:1130157)
at _next (address at index.android.bundle:1:1130415)
at callReaction (address at index.android.bundle:1:553154)
at anonymous (address at index.android.bundle:1:553420)
at flush (address at index.android.bundle:1:558771)
at tryCallOne (address at InternalBytecode.js:1:1180)
at anonymous (address at InternalBytecode.js:1:1874)
This works fine on version 2025-07, but not 2026-01.
NOTE: while I can only inspect this error on Android, I see the same symptoms on my iPad.
For context, my app enables merchants to add customers to the POS cart by scanning their barcode. The majority of merchants use barcodes issued by the app. Such barcodes have customer IDs encoded. However, some merchants issue their own barcodes. Currently, in production, the app calls setCustomer, and if it throws, then the app falls back to its database lookup.
I’d like to avoid fetching the customer ID via the Shopify admin API before calling shopify.cart.setCustomer, as it would be an additional redundant request. The code in shopify.cart.setCustomer already checks if the customer exists.
Would it be possible to get this fixed in version 2026-04?
Hi Galmis, thanks for flagging this. We’ll provide an update here once we’ve resolved that error.
Regarding the issue where setCustomer doesn’t resolve, I wasn’t able to reproduce it. The promise resolves with undefined , the customer gets set to the cart, and the toast appears with this simple setup:
Sorry for leaving some details out. The issue appears to be more subtle. Please see the snippet below.
export function Example() {
useEffect(() => {
const unsubscribeScanner = shopify.scanner.scannerData.current.subscribe(
async ({ data }) => {
if (!data) return;
shopify.toast.show(`Scanned: "${data}"`);
navigation.back();
// It works when calling navigation.navigate instead of navigation.back. Why is navigate async, but back is not?
// await navigation.navigate("/");
try {
await shopify.cart.setCustomer({
id: Number(data),
});
shopify.toast.show(`Customer set successfully`);
} catch {
shopify.toast.show(`Error setting customer`);
}
}
);
return () => unsubscribeScanner();
}, []);
// Go to the camera page and wait for the timeout - it works as expected
// useEffect(() => {
// const timeout = setTimeout(async () => {
// navigation.back();
// try {
// await shopify.cart.setCustomer({
// id: <customer ID here>,
// });
// shopify.toast.show(`Customer set successfully`);
// } catch {
// shopify.toast.show(`Error setting customer`);
// }
// }, 5000);
// return () => clearTimeout(timeout);
// }, []);
if (navigation.currentEntry.url === "/camera") {
return <CameraPage />;
}
return (
<s-page heading="Default page">
<s-button onClick={() => navigation.navigate("/camera")}>
Open camera page
</s-button>
</s-page>
);
}
function CameraPage() {
useEffect(() => {
shopify.scanner.showCameraScanner();
return () => {
shopify.scanner.hideCameraScanner();
};
}, []);
return <s-page heading="Camera page"></s-page>;
}
setCustomer doesn’t resolve when navigating back after a camera scan event. This is the actual issue. I think the error in the description is a red herring.
It works fine when calling await navigation.navigate(“/”) instead of navigation.back(), but it adds an entry to the navigation history stack, which I’d like to avoid. I’m curious why navigate returns a promise, but back doesn’t.
Interestingly, it also seems to work fine when navigating back and setting a customer after a timeout instead of a scan event. I’m still trying to wrap my head around how the new navigation works. I’ve noticed that sharing global state between views no longer works. Example:
export function ExampleTwo() {
const [count, setCount] = useState(0);
if (navigation.currentEntry.url === "/two") {
return (
<s-page heading="Two page">
<s-button onClick={() => navigation.back()}>Go back</s-button>
<s-text>Count: {count}</s-text>
<s-button onClick={() => setCount((c) => c + 1)}>Increment</s-button>
</s-page>
);
}
return (
<s-page heading="Page one">
<s-button onClick={() => navigation.navigate("/two")}>
Go to page two
</s-button>
<s-text>Count: {count}</s-text>
<s-button onClick={() => setCount((c) => c + 1)}>Increment</s-button>
</s-page>
);
}
When navigating to page two, the count always resets. I wonder if setCustomer doesn’t resolve because it’s being called by the no longer active view? Whereas the timeout example works, because the timeout was initiated by the initial view.
It’d be really nice if there was any documentation explaining how it all works under the hood.
Thanks so much for the detailed context, exactly what we needed!
Looks like there are a few issues here:
Uncaught exception when Customer not found
navigate.back doesn’t return a Promise
Global state sharing no longer works
Thanks for flagging these issues with us. We’re not able to provide an ETA on when these will be fixed, but will provide an update in this thread once we do