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

# Troubleshooting

> Diagnose and resolve common Proview SDK integration issues across all modules

This page covers issues that apply to the Proview SDK as a whole — loading, initialization, authentication, and module wiring. It is not specific to any single module.

## Before you start: turn on error reporting

Register the global error handler **before** calling `Proview.init()`. Most integration failures surface here rather than as thrown exceptions.

```js theme={null}
window.proviewOnLoad = async function () {
  Proview.onError(function (err) {
    console.error('[Proview]', err.type, err.code, err.message);
    if (err.validationErrors) console.error(err.validationErrors.formattedMessage);
  });

  const success = await Proview.init({ /* ... */ });
  if (!success) {
    console.error('[Proview] init returned false — check the error handler output above');
  }
};
```

<Note>
  `Proview.onError` supports a **single** handler. Registering a second handler replaces the first. If your app already registers one, fan out from inside that handler instead of calling `onError` again.
</Note>

The error object passed to the handler has this shape:

| Field              | Type                                | Description                                                                                                            |
| ------------------ | ----------------------------------- | ---------------------------------------------------------------------------------------------------------------------- |
| `code`             | `string`                            | Stable identifier for the failure.                                                                                     |
| `message`          | `string`                            | Human-readable reason, for logs.                                                                                       |
| `type`             | `'critical' \| 'warning' \| 'info'` | `critical` means core functionality is impacted.                                                                       |
| `validationErrors` | `CustomValidationError`             | Present on schema-validation failures. A single object with `issues` (one entry per bad field) and `formattedMessage`. |

For the full code list and per-code handling, see the [Error Reference](/sdk/errors).

## The SDK never loads

**Symptom:** `window.Proview` is `undefined`, or your `proviewOnLoad` callback never fires.

Work through these in order:

1. **Check the script actually loaded.** Open DevTools → Network and look for `https://sdk.tlv.cx`. A `4xx`/`5xx` or a blocked request means the bundle never arrived.
2. **Check your Content Security Policy.** A CSP violation is reported in the Console, not the Network tab. The SDK needs the directives listed in [Getting Started](/sdk/getting-started#content-security-policy-csp).
3. **Check you are on HTTPS.** The SDK requires a secure context. It will not run on `http://` origins other than `localhost`.
4. **Check the callback is defined before the loader runs.** `window.proviewOnLoad` must be assigned in a script that executes *before* the loader `<script>` tag. If you define it afterwards, the SDK may have already fired and your callback is never invoked. This is the single most common cause of a callback that never runs.
5. **Add an `onerror` handler to the script tag** so a failed load is visible instead of silent:

   ```html theme={null}
   <script
     src="https://sdk.tlv.cx"
     async
     crossorigin="anonymous"
     onerror="console.error('Proview SDK failed to load')"
   ></script>
   ```

## `Proview.init()` fails

**Symptom:** `Proview.init()` resolves to `false`, or your error handler reports a `critical` error with `validationErrors`.

| Cause                            | How to confirm                                                          | Fix                                                                                                                                          |
| -------------------------------- | ----------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
| Missing or empty `dsn`           | `MISSING_REQUIRED_FIELD` — `Missing required field: dsn`                | Pass the project DSN issued for your tenant. It differs per environment (dev / staging / prod).                                              |
| Wrong DSN for the environment    | Init fails only in one environment                                      | Use the DSN that matches the loader URL you are pointing at.                                                                                 |
| Missing or rejected `credential` | `AUTH_ERROR` or `UNAUTHORIZED`                                          | Pass an auth strategy — see [Authentication](#authentication-failures).                                                                      |
| Module not declared              | `Proview.<module>` is `undefined` at runtime                            | Add the module's factory to the `modules` array: `modules: [Proview.session(), Proview.form()]`.                                             |
| Required module fields missing   | `INVALID_CONFIG` — `validationErrors.issues` lists the offending fields | Supply the fields the module requires. For proctoring, `identifier`, `attendee.identifier`, and `workflow_step.identifier` are all required. |

## A module is `undefined`

**Symptom:** `TypeError: Cannot read properties of undefined (reading 'start')` — or the same for `mount`, `init`, `fetchMeetings`.

A module namespace only exists after its factory has been declared **and** `Proview.init()` has resolved. Two common mistakes:

```js theme={null}
// Wrong — module never declared
await Proview.init({ dsn, credential, modules: [Proview.scheduler()] });
Proview.form.mount({ ... });             // Proview.form is undefined

// Wrong — used before init resolves
Proview.init({ dsn, credential, modules: [Proview.form()] });  // not awaited
Proview.form.mount({ ... });             // race: may run before init completes
```

Always `await` `Proview.init()` and declare every module you intend to use.

## Single-page applications

**Symptom:** The SDK re-initializes, duplicates listeners, or throws on client-side route changes.

Load the loader script **once per page load**, not once per route. Guard the injection:

```js theme={null}
function loadProview() {
  if (window.Proview || document.getElementById('proview-sdk')) return;

  const s = document.createElement('script');
  s.id = 'proview-sdk';
  s.src = 'https://sdk.tlv.cx';
  s.async = true;
  s.crossOrigin = 'anonymous';
  s.onerror = () => console.error('Proview SDK failed to load');
  document.head.appendChild(s);
}
```

Call `Proview.init()` once as well — inside `window.proviewOnLoad`. On subsequent route changes, reuse the already-initialized modules rather than re-running init.

## Authentication failures

**Symptom:** Init succeeds but module calls fail with a forbidden / unauthorized error.

* Auth strategy is set globally via `credential` on `Proview.init()`. Omitting it applies [`DefaultAuthStrategy`](/sdk/authentication#defaultauthstrategy).
* Tokens are short-lived. One fetched at page load may already be expired by the time a long-lived session calls a module method — fetch it as late as you can, and refresh on expiry.

## Nothing renders

**Symptom:** Init and start both succeed, but no UI appears.

1. **Check the mount target exists.** `containerId` must name an element that is already in the DOM when you mount — for example `Proview.scheduler.mount({ mountMode: { mode: 'inline', containerId: 'proview-scheduler-root' } })`. In a component framework, mount from the effect that runs after render, not during it.

2. **Check the target is visible and has size.** A container with `display: none`, zero height, or a collapsed flex parent renders nothing:

   ```js theme={null}
   const el = document.getElementById('proview-scheduler-root');
   console.log(el, el && el.getBoundingClientRect());
   ```

3. **Check for a stacking / overflow conflict.** Modal and side-panel layouts are positioned relative to the viewport; an ancestor with `overflow: hidden` or a high `z-index` can clip them.

4. **For proctoring, confirm the session actually started.** Do not gate your UI on the loader script — wait for `Proview.session.start()` to resolve.

## Camera and microphone permissions

**Symptom:** The permission prompt never appears, or is denied immediately.

* The browser only prompts on a **secure context** (HTTPS or `localhost`).

* If the host page or an outer iframe already declined the permission, the browser will not re-prompt. The user must reset it from the site settings.

* When embedding the host page in an iframe, forward the permissions:

  ```html theme={null}
  <iframe src="..." allow="camera; microphone; display-capture"></iframe>
  ```

* Some enterprise browser policies block camera access outright. Check `chrome://policy` / equivalent before assuming an SDK fault.

## Getting help

If the steps above do not resolve the issue, contact [support@talview.com](mailto:support@talview.com) with:

* The SDK version and loader URL you are using
* Your project DSN (not the credential or token)
* The `code`, `type`, and `message` from your `onError` handler — see the [Error Reference](/sdk/errors)
* A HAR file or Console log covering the failure
