Troubleshooting
The symptoms we actually see, what each one means, and the fix — check here before writing to support.
Symptom-first list of the problems integrators actually hit. Every fix links the page that explains the mechanism.
Storefront
The save button renders nothing
An inert <envie-button> tag means the components bundle never loaded — the app embed is off.
Theme editor → App embeds → Envie → enable, then reload. The app's home page in the Shopify
admin verifies this for you ("Verified" badge on step 1).
If the embed is on and the element is still dead, check the browser console for a blocked script (a CSP or an aggressive performance app can strip deferred scripts).
The button renders but clicking does nothing (or flips back)
The optimistic toggle reverted — the API rejected the save. Listen for the reason:
document.addEventListener("envie:error", (event) => console.log(event.detail.message));Usual causes, in order: missing handle on a hand-written tag
(validation) · guest saves disabled on the shop
(guest-disabled) · free-plan cap reached
(plan-limit).
Browser console shows a CORS error (headless)
Your storefront's origin isn't declared. Envie → Developers → Headless origins — add the
exact origin (https://shop.example.com, no path, no trailing slash). Takes effect within a
minute. Auth reference.
401 invalid-signature from a Liquid theme
Theme code is calling api.getenvie.com directly. From Liquid, requests must go through the app
proxy on the shop's own domain (/apps/envie/…) — only that path carries Shopify's signature.
createEnvie() with no options does this for you.
Details.
Identity
The wishlist didn't follow the shopper after login
- Liquid: the merge runs on the first page view after login — check the shopper actually
loaded a page with the embed active. The merge is once per (browser, customer); a shopper who
cleared
localStoragegets a fresh guest list by design. - Headless:
identify()must run server-side with the shopper'senvie:aidfrom their browser. The merge guide has the full flow; the usual bug is a hardcoded or missinganonymousId.
identify-forbidden in the console
identify() was called from browser code in public mode. It only works server-side —
why and how.
Server-side
Webhook signatures never verify
Nine times out of ten: verifying against re-serialized JSON instead of the raw request bytes. Keep the raw body for the HMAC — complete working example in the webhooks guide. Also check you're using the endpoint's own secret (each endpoint has its own, shown at creation).
Import finished but items are "missing"
Open the dry-run report (resultUrl): rows that resolve to no customer are skipped and listed
with line numbers — deleted customers and guest-only rows are the common bulk. imported: 0 on a
re-run means everything was already there (imports are idempotent).
Import rules.
429s under normal load
You're polling something that should be pushed. Budget math and the fixes: rate-limited.
Playground
Every playground request returns 401
The playground sends exactly what you give it: private endpoints need an env_sk_… key in the
Authorization field; storefront endpoints in public mode need X-Envie-Shop +
X-Envie-Public-Key. And anything you paste into a browser should be a key you can rotate.
Still stuck?
Support — include the requestId from the error response and you'll skip a
round trip.
Import from Swym or Swish
Move an existing wishlist install to Envie without losing shopper data — dry-run first, idempotent, with a full report of anything skipped.
Authentication & conventions
Calling the REST API without the SDK: the three auth modes as raw headers, plus the conventions every endpoint shares.