Skip to main content
Use this page as your first stop when the SDK fails to load, the embedded widget does not render, or downstream requests do not behave as expected. Each issue below is organized by symptom, cause, and fix so your team can isolate the problem quickly before reaching out for help.

Token & authentication issues

Symptom: The SDK shows an authentication error, or the embedded experience never boots.Cause: The Embed Token was signed with the wrong secret, or the secret does not match the Connected App identified by iss.Fix: Verify that iss matches your NSDK_CONNECTED_APP_CLIENT_ID and that the token is signed with the matching NSDK_CONNECTED_APP_SECRET_KEY on your backend only.
Symptom: Token validation fails even though the token structure looks correct.Cause: The aud claim is set to the wrong value.Fix: Set aud exactly to nsdk-embed. Do not reuse access-token or refresh-token audiences from other systems.
Symptom: Newly minted tokens are treated as expired or not yet valid.Cause: iat and exp were generated in milliseconds instead of seconds, or the backend server clock is out of sync.Fix: Generate iat and exp as Unix timestamps in seconds and keep your backend clock synchronized with a reliable time source.
Symptom: The SDK rejects the token immediately during validation.Cause: One or more required claims are missing or empty.Fix: Include iss, sub, aud, iat, exp, and jti on every token. Also provide nsdk.user.name and nsdk.user.email so the embedded session has the expected user context.
Symptom: The token works in local testing sometimes, but fails in real user flows or after page delays.Cause: The token is minted too early, cached too long, or given an unnecessarily short lifetime.Fix: Fetch the token only after the tenant user session is established and close to mount time. Keep the TTL short but practical, typically 5–15 minutes.

Frontend & embedding issues

Symptom: NSDK is undefined, or nsdk-loader.js never appears in the browser network log.Cause: NSDK_BASE_URL is wrong, the script URL is blocked by CSP, or the browser cannot reach the hosted SDK origin.Fix: Confirm the exact loader URL, open it directly in the browser, and allow the SDK origin in your script-src policy where required.
Symptom: The page loads successfully but no widget appears.Cause: The mount container is missing, rendered too late, uses the wrong selector, or is missing required declarative attributes.Fix: For declarative mode, ensure the container exists before the SDK initializes and includes data-nsdk="true". For imperative mode, confirm the mount selector resolves to exactly one element.
Symptom: The loader runs, but the embedded frame is blocked or the browser console shows CSP errors.Cause: Your host application does not allow the SDK origin in frame-src, child-src, or related policies.Fix: Update your CSP to allow the Narrative SDK origin for framed content and any required network requests from the embedded experience.
Symptom: The container is present, but the embedded experience behaves as if no token was supplied.Cause: The token is set after boot, the wrong attribute or property is used, or the runtime reads the container before the token handoff completes.Fix: In declarative mode, set data-nsdk-token before the SDK boots. In imperative mode, pass embedToken directly in NSDK('boot', ...) and confirm the token value is not empty.

Backend & network issues

Symptom: The frontend cannot fetch the Embed Token even though the backend route exists.Cause: The token endpoint is on a different origin and CORS is not configured for the tenant frontend.Fix: Prefer a same-origin token route. If cross-origin is required, explicitly configure CORS for the tenant frontend origin and any credentialed requests.
Symptom: The wrong user receives a token, or unauthenticated requests can still mint one.Cause: The backend route trusts browser input without validating the tenant application’s own authenticated user session.Fix: Require an authenticated tenant session on the backend before minting each token, and derive the token subject from trusted server-side user context.

Session & runtime issues

Symptom: The shell or frame appears, but the user is shown a restricted or unauthenticated experience.Cause: The token was minted for the wrong tenant user, the tenant session changed before boot, or a stale token was reused.Fix: Mint a fresh token for the current authenticated tenant user, avoid browser-side token storage, and retry the flow with a newly issued token.
Symptom: The widget works on the first route load but breaks after navigating within a single-page application.Cause: The host app unmounted the container, reused a stale DOM node, or never cleaned up a previous runtime instance.Fix: Recreate the mount container on route entry, re-run boot when the page remounts, and call NSDK('destroy') during cleanup when using imperative mode.

Data & product surface issues

Symptom: The embedded widget boots, but downstream product requests still return 401.Cause: Bootstrap succeeded, but the requested product surface, tenant mapping, or user-level access is not ready for the downstream request.Fix: First confirm the widget booted with a fresh token. Then verify the user, tenant, and product surface access expected by the destination API or experience.
Symptom: The widget loads, but expected account, transaction, or customer data is missing or stale.Cause: Upstream data has not finished syncing yet, the wrong environment is being tested, or the tenant-user mapping does not line up with the source data.Fix: Confirm the correct environment, allow time for source-data processing, and validate that the target tenant user has the expected records available to the provisioned experience.

Still stuck?

If you are still blocked after working through this guide, use Support for the contact path and the checklist of details to include in your request.