> ## Documentation Index
> Fetch the complete documentation index at: https://docs.catenatelematics.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Troubleshooting

> Go from what you see on the page to the cause and the fix, and the cases where no callback arrives

Each entry starts with what you see on the page. The cause and the fix follow, and the link at the end goes to the section that explains the mechanism.

Symptoms the React wrapper can cause on its own, such as two surfaces on the page or an overlay left behind, are on the [React](/get-started/connect-sdk/react#troubleshooting) page.

## Symptoms

<AccordionGroup>
  <Accordion title="The surface shows &#x22;Continue&#x22; instead of the flow">
    You see a **Continue** button where the flow should be.

    **Cause.** The package could not confirm that this browser will run the flow in a frame. The possible reasons:

    * The launching page's origin is not registered against your embed key, or the key is unknown or revoked. The console shows a frame-ancestors violation.
    * The browser refused the flow's cookie in a frame.
    * Your page's Content Security Policy blocks the connect origin from being framed.
    * The probe frame never answered in time: a blocked request, a frame that never loaded, or a slow network.
    * The check passed, but the flow's iframe loaded and never reported it was ready, usually because the connect origin refused to be framed. The button appears about eight seconds after that iframe loads.
    * This page already probed once with no answer. The verdict is kept until the page reloads.

    The flow still works through the button. It opens the flow in a window, or in the tab when the browser blocks the window too and your page is not itself framed (see the next entry). On an unregistered origin or with an unknown key, though, the window posts nothing to your page.

    **Fix.** When the origin is the cause, register the exact origin: scheme, host and port must match, and `www` and the apex are different origins. Registered origins must be `https`, or `http` on `localhost`.

    When the policy is the cause, allow the origin of your invitation URL in `frame-src`. If your policy has no `frame-src`, use `child-src`, and if it has neither, use `default-src`. The cookie probe is a frame on the same origin and falls under the same directive. The package makes no requests of its own, so no other directive needs to change.

    A refused cookie decides within one round trip. A probe frame that loads and never answers, including on an unregistered origin, waits about six seconds after it loads before the button appears, and one that never loads at all waits up to eight. The flow's own iframe waits eight seconds after it loads, as in the last cause above. Only the policy and origin cases show in the browser console, as a violation report. A refused cookie or an unanswered frame on a registered origin leaves nothing there.

    See [the three modes](/get-started/connect-sdk/how-it-works#the-three-modes).
  </Accordion>

  <Accordion title="Clicking &#x22;Continue&#x22; navigates the tab away">
    You click **Continue** and the whole tab leaves your page.

    **Cause.** The browser blocked the window too, so the flow continued in the tab. This is the third mode, working as designed. A page inside a frame is never navigated this way: the surface asks the user to allow pop-ups and press **Continue** again instead.

    **Fix.** Allow popups on the launching page. If your invitation has redirect URLs, make sure both pages call `resume()`. Without them, the flow ends on its last screen and your webhooks are the record.

    See [the three modes](/get-started/connect-sdk/how-it-works#the-three-modes) and [resume()](/get-started/connect-sdk/javascript-reference#resume-options).
  </Accordion>

  <Accordion title="A provider's sign-in window is blocked">
    The flow shows a message saying the sign-in window was blocked.

    **Cause.** Popups are not allowed on the launching page. The flow stays up with the form intact, and nothing fires until the setting allows the window.

    **Fix.** Allow popups on the launching page.

    See [the provider window](/get-started/connect-sdk/how-it-works#the-provider-window).
  </Accordion>

  <Accordion title="No callback ever arrives">
    The flow runs, but none of your callbacks fire.

    **Cause.** Most often the launching page's origin is not registered against your embed key, or the key is unknown or revoked. The two look the same from your page. The flow falls back to the popup and runs there, but its messages are addressed elsewhere, or for an unknown or revoked key not sent at all. The other causes:

    * A window or link you opened yourself used `noopener`. The package never opens with `noopener`.
    * The launching page sends `Cross-Origin-Opener-Policy: same-origin`, which severs the popup.
    * The flow ran in the tab and no page called `resume()`.
    * The destination page is on another origin.
    * The user left.

    **Fix.** Check each case in [When you receive nothing](#when-you-receive-nothing). Your [webhooks](/api-reference/webhooks/overview) are the record in every case.
  </Accordion>

  <Accordion title="onClose arrives the moment the popup opens">
    You press **Continue**, the popup opens, and `onClose` arrives straight away with no outcome. The user carries on in the window.

    **Cause.** The launching page sends `Cross-Origin-Opener-Policy: same-origin`, which disconnects it from the popup as soon as the popup loads the flow. From your page the window looks closed. The console shows a warning from the package naming the header.

    **Fix.** Serve the launching page with `same-origin-allow-popups` instead. It keeps the popup connected and changes nothing else.

    See [When you receive nothing](#when-you-receive-nothing).
  </Accordion>

  <Accordion title="The surface closes right after it opens">
    The flow appears and `onExit` arrives at once, followed by `onClose`, with `reason` set to `invalid_invitation` or `invitation_unavailable`.

    **Cause.** The flow could not load the invitation in the link. Behind the callbacks the flow shows an error screen, which goes away when you take the surface down on `onClose`.

    **Fix.** For `invalid_invitation`, check the invitation you launched with and create a new link. For `invitation_unavailable`, offer a retry, since the link may be fine. Show the user your own message either way.

    See [onExit when the invite link never loaded](/get-started/connect-sdk/events#onexit-when-the-invite-link-never-loaded).
  </Accordion>

  <Accordion title="open() throws">
    Calling `open()` throws an error and nothing renders.

    **Cause.** `open()` throws a `TypeError` if the invitation URL does not parse, is not http or https, or is http on any host other than `localhost`, `127.0.0.1` or `[::1]`. It also throws if it is called before `<body>` exists with no `container`, or outside a browser.

    **Fix.** Pass an `https` invitation URL. Plain http is accepted on `localhost`, `127.0.0.1` and `[::1]` only. Call `open()` in a browser, after `<body>` exists or with a `container`.

    See [open()](/get-started/connect-sdk/javascript-reference#open-options).
  </Accordion>

  <Accordion title="resume() fires on a page the flow did not return to">
    A `resume()` callback fires on a page the user reached some other way.

    **Cause.** A redirected launch left this tab within the last 30 minutes and was abandoned, and `resume()` consumed its record.

    **Fix.** Call `resume()` on the two destination pages and nowhere else.

    See [resume()](/get-started/connect-sdk/javascript-reference#resume-options) and [When you receive nothing](#when-you-receive-nothing).
  </Accordion>

  <Accordion title="The flow renders but your branding is ignored">
    The flow appears with your account's branding instead of the color or logos you passed.

    **Cause.** One of these:

    * The embed key does not resolve to a registered, active key. `brandColor`, `brandSecondary`, `logoUrl` and `logoUrlDark` are dropped and the branding configured on your account applies.
    * A value was rejected. `brandColor` and `brandSecondary` must contain exactly six hex digits, with an optional leading `#`, and logo URLs must be absolute `https`.
    * A logo failed to load. That leaves its slot empty.
    * You passed `variant: "card"`. The logo then shows only on the consent card.

    **Fix.** Use an embed key that is registered and active, and check each value against the rules.

    See [presentation options](/get-started/connect-sdk/javascript-reference#presentation-options), which explains why branding needs your embed key to resolve.
  </Accordion>

  <Accordion title="A second launch does nothing">
    Calling `open()` again does not start a new flow.

    **Cause.** One flow runs at a time. The call brought the live launch back and returned its handle: the popup window if one is open, otherwise the overlay. In a container it does nothing visible.

    **Fix.** Let the live flow end, or call `destroy()` on its handle, before launching again.

    See [one flow at a time](/get-started/connect-sdk/javascript-reference#one-flow-at-a-time).
  </Accordion>
</AccordionGroup>

## When you receive nothing

Each of these is a real outcome, not an error to surface. Your connection [webhooks](/api-reference/webhooks/overview) remain the record. The absence of a callback is never proof that nothing happened.

1. **Unregistered origin.** The page you embed from is not registered against your embed key. The flow falls back to the popup and runs, but every message is addressed elsewhere and the browser drops it. This is the origin check doing its job.
2. **Unknown or revoked embed key.** This is deliberately indistinguishable from an unregistered origin. The flow falls back to the popup and runs, and sends no messages at all. You cannot tell the two apart, and neither can an attacker.
3. **Severed opener.** Opening the flow through a window or link of your own with `noopener` removes the channel the completion travels on. The user still finishes. The package never opens with `noopener`.
4. **`Cross-Origin-Opener-Policy: same-origin` on the launching page.** In the popup mode, the browser cuts your page off from the window as soon as it loads the flow. From your page the window looks closed, so you get `onClose` with no outcome shortly after the click, while the user carries on in a window your page cannot hear or close. If your invitation has redirect URLs, the flow then finishes by sending that window to one of them. Without them it stays on its last screen. The package logs a console warning when a window closes this fast. Serve the page with `same-origin-allow-popups` instead.
5. **Redirect mode with no `resume()` call.** The flow completed in your tab and nothing was listening when it came back.
6. **A `resume()` destination on another origin.** The outcome crosses the navigation in a `sessionStorage` record, and that is partitioned by origin as well as by tab. Both destination pages must be on the same origin as the page that launched, or `resume()` emits nothing.
7. **The user abandoned the surface.** No terminal event was produced because the flow never reached one. In a frame, a user who connects and never presses **Done** produces `onConnection` but no `onSuccess`. The connection is real.

<Warning>
  One caveat in the other direction: a callback means a redirected launch left this tab recently, not that this page was reached from the flow. An abandoned launch stays recorded for up to 30 minutes, and a `resume()` inside that window will consume it. Put the call on your two destination pages and nowhere else.
</Warning>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.