Reference
Troubleshooting
The snags people actually hit: a CORS error that is really a 500, walkthroughs that come back empty, and steps that show text but never point at anything.
A CORS error, or a 500 on the preflight
If the browser reports a CORS failure and the preflight OPTIONS request returns a 500 with no CORS headers, the cause is almost always that your origin is not allowed and the backend rejected it by throwing rather than denying cleanly.
- The origin must match exactly.
http://localhost:3000,http://localhost:3001, andhttps://yourapp.comare three different origins. Scheme, host, and port all count. - For a distributed SDK you should not hand-list every origin globally. Keep the SDK routes open at the CORS layer and gate origins per key, through the publishable key's own origin allowlist.
Find the exact origin
The browser console names it: "from origin 'X' has been blocked". Allow X verbatim.The walkthrough comes back empty
You ask for something and get "no walkthrough matches that yet". Open the network tab: you will usually see a match call that found nothing, then a generate call that also returned empty.
The reason is almost always missing vocabulary. The generator will not invent selectors, so on a site it knows nothing about it has nothing to build from. Populate vocabulary (upsert a few elements, crawl, or import) and the same request generates a real walkthrough.
Steps show text but do not point at anything
The walkthrough starts, the card shows the instruction, but no cursor lands on an element. That means the step's selector did not match anything on the page.
- Confirm the element exists when the step runs. In single-page apps it may render after a delay; the SDK retries briefly, but a slow async element can still miss.
- Prefer a stable
data-nudge-idover a structural selector. A:nth-childselector breaks the moment the layout shifts. - Set
fallback_selectorson the step so a single change does not break it.
The launcher never appears
- Check
mount()actually ran, in the browser, afterinit(). - If you render on the server, the call must be client-only. Running it during SSR does nothing because there is no
window. - If you set
trigger: { mode: "programmatic" }, there is no launcher by design. Start walkthroughs from your own UI. - Check the console and network tab for a failed load or a 401 from a bad key.
Requests return 401
The key was rejected. Either it is wrong, revoked, or it is a secret key used in the browser. Secret keys (sk_) are server-only; the browser must use a publishable key (pk_). If the key has an origin allowlist, the request must come from one of those origins.
A real 500 on a route (not the preflight)
If a request still 500s after CORS is sorted, it is a server-side error. Check your backend logs for the stack trace. Common causes are a missing environment variable (the backend hard-fails in production without REDIS_URL, for instance) or a database call hitting a table that was not migrated. The trace names the exact line.