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

# Troubleshooting

> Diagnose boot, chat, voice, and visible-page issues, and learn what the guide can and cannot see.

Most launch issues fall into one of four buckets: the guide does not mount, it mounts but does not answer, voice does not start, or the guide cannot reach a control on the page. Work through the symptom that matches, then confirm the result in your browser.

## Common symptoms

<AccordionGroup>
  <Accordion title="The guide does not appear" icon="eye-off">
    The boot script runs but no launcher renders.

    <Steps>
      <Step title="Confirm the boot script attributes">
        The script needs both `data-app-id` (your app ID, the `gp_` token) and `data-gp-api`. Without `data-gp-api` the worker is unreachable: the runtime logs an error and returns an empty URL, so nothing mounts. See [Install Puntego](/install) for the full snippet.
      </Step>

      <Step title="Check the domain allowlist">
        The current hostname must be on the workspace domain allowlist, and its DNS TXT verification must have succeeded. Add and verify it from **Dashboard → Settings → Domains**. Review the steps in [Authorize your domains](/domains).
      </Step>

      <Step title="Pass the nonce on strict CSP sites">
        If your site uses strict CSP, set the nonce on both `nonce` and `data-nonce`, and allow the worker origin and microphone Permissions-Policy as described in [Content Security Policy](/csp).
      </Step>

      <Step title="Check the route rules">
        `data-routes` is evaluated at load (and re-checked on SPA route changes). If any allow rule is present, the path must match one to mount; a leading `!` deny always wins. Confirm the current path is not excluded in [Configuration](/configuration).
      </Step>
    </Steps>
  </Accordion>

  <Accordion title="The guide loads but does not answer" icon="message-square-off">
    The launcher renders but chat returns nothing.

    * Confirm the `/boot` request succeeds. `/boot` returns `success`, or one of `400` (invalid request), `403` (`boot/origin_not_allowed` or `boot/tenant_not_enabled`), `429` (rate limit, with a `Retry-After` header), or `503` (killswitch). It never returns `401`. A `403` here usually means the hostname is not allowlisted or the workspace is not enabled for rollout.
    * Confirm `/chat` is authorized. Each request needs a valid `Authorization: Bearer <visitor-jwt>`. That token is minted at `/boot` and has roughly a 15-minute TTL, so a missing, invalid, or expired token returns `401` (`chat/unauthorized`, or `jwt_expired` once it ages out). The fix is almost always an upstream `/boot` failure.
    * `/chat` also enforces visitor and workspace rate limits, returning `429` with a `Retry-After` header when exceeded. See [Rate limits](/rate-limits).
    * If the killswitch (`GP_KILLSWITCH=true`) is active, `/boot` returns `503` and the embed silently no-ops by design.
    * If consent mode requires opt-in and the visitor has not accepted, the guide will not collect input or respond. Confirm the mode in [Privacy and PII](/privacy-and-pii).
  </Accordion>

  <Accordion title="Voice does not start" icon="mic-off">
    The microphone or spoken responses are unavailable.

    * Voice is optional per workspace. Confirm it is enabled for this workspace before debugging further.
    * When voice provider credentials are absent, the system falls back to an internal mock voice. This is credential-based, so it applies in production as well as local development, not only local development.
    * Strict-CSP sites need a microphone `Permissions-Policy`; without it the browser blocks capture. See [Content Security Policy](/csp).
    * Push-to-talk on the `V` key defaults to on. If you have set `data-voice-hotkey` to opt out, the key will not wake voice.
  </Accordion>

  <Accordion title="The launcher looks different on mobile" icon="smartphone">
    The experience changes on touch or narrow screens.

    The runtime detects touch-primary or narrow (under 768px) screens and switches to the bubble experience, but only when the launcher mode is `cursor`. With the default floating launcher, narrow and touch screens keep the floating button. If you expected the floating button and see a bubble, check whether `data-launcher-mode` is set to `cursor` in [Configuration](/configuration).
  </Accordion>
</AccordionGroup>

## What the guide cannot see

The guide reads the live DOM of the surface in front of the visitor. A few surfaces fall outside that line of sight by design.

| Surface                                | Why it is invisible                                                                                                                                                                           | What to do                                                                                                                                                   |
| -------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Canvas or WebGL surfaces               | When a canvas covers more than \~60% of the viewport, the runtime enters canvas mode because the underlying controls are not exposed as DOM targets.                                          | Keep the critical path you want guided in real DOM controls, and treat canvas-first products (design tools, whiteboards, game UIs) as typed-assistant first. |
| Iframes (same-origin and cross-origin) | The runtime does not descend into any iframe. Both same-origin and cross-origin frames are invisible, so embedded payment fields, support widgets, video, maps, and CAPTCHA are out of reach. | Keep these flows outside the "point here next" promise, or render the critical controls in the top-level document.                                           |
| Shadow DOM (open and closed)           | Shadow DOM is invisible for both closed and open roots unless you register it.                                                                                                                | Register each root with `registerShadowRoot(root)` so the guide can inventory and point at its controls. See the [Guide Tools SDK](/guide-tools-sdk).        |
| Unloaded or restricted content         | The guide only sees what the current visitor has loaded and is allowed to view.                                                                                                               | Make sure the target control is rendered and accessible to the visitor before asking the guide to point at it.                                               |

## What that means for you

* Prefer real DOM controls for the critical path you want Puntego to guide.
* Keep payment fields, support widgets, and CAPTCHA flows outside the "point here next" promise, since they typically live in iframes.
* Register custom shadow roots up front so component internals are pointable.

## Next steps

<CardGroup cols={2}>
  <Card title="Authorize your domains" icon="globe" href="/domains">
    Add a hostname, verify the DNS TXT record, and clear `403` boot errors.
  </Card>

  <Card title="Content Security Policy" icon="shield-check" href="/csp">
    Allow the worker origin, set the nonce, and grant the microphone policy for voice.
  </Card>

  <Card title="Errors" icon="circle-alert" href="/errors">
    Look up the exact `namespace/reason` envelope and status code you received.
  </Card>

  <Card title="Guide Tools SDK" icon="code" href="/guide-tools-sdk">
    Register shadow roots and targets so the guide can reach more of your page.
  </Card>
</CardGroup>
