> This page is for Experience Orchestration.

> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://contentful.com/developers/docs/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://contentful.com/developers/docs/_mcp/server.

# Errors and debugging

> Debug experiences, read diagnostics, and handle failures with the Experiences SDK.

> **Info**
>
> Experiences SDK is currently available in alpha. APIs are unstable and subject to change.

When `fetchExperience` returns a result, any potential errors within that experience are isolated to the affected node, allowing the rest of the page to render normally. These errors can include a malformed payload, a failing `resolveData` function, an unresolved design token, an unregistered component, or a component that throws while rendering. Each error is reported as a diagnostic you can inspect for troubleshooting.

`fetchExperience` itself throws when the experience doesn't exist or the request fails, so handle those errors in your route. See [Handle errors](/developers/docs/experience-orchestration/experiences-sdk/fetch-experiences#handle-errors). In Svelte, a component that throws during server rendering also fails the page. See [Server and client differences](#server-and-client-differences).

## Debug mode

Debug mode shows what the SDK received and how it resolved it. To turn it on, include `debug: true` in the resolve options of `fetchExperience`, as follows:

```ts
const experience = await fetchExperience(experienceOptions, clientOptions, {
  config: experienceConfig,
  debug: true,
});
```

With debug mode on, the SDK:

* **Logs** the fetch, the raw payload, the resolution steps, and the time each `resolveData` function takes, with the prefix `[experiences:debug]`.
* **Shows unregistered components** as a **Missing component** box that names the component ID. Without debug mode, they render nothing.
* **Adds a debug panel** after the experience, with the resolved experience as JSON and a list of diagnostics.

You can turn it on from any signal: a `?debug=true` query parameter in development, a feature flag, or the environment. Debug mode is independent of `preview`, which selects the delivery or preview API. The renderer's `debug` prop overrides the experience's value.

Components can read `debug` from the render context, with `useExperience().debug` in React, `getExperience().debug` in Svelte, or `injectExperience()` in Angular, to add their own debug output.

### Mount the debug panel yourself

The renderers mount the debug panel when debug mode is on. To place it yourself, mount `DebugExperience` with the experience:

```tsx
import { DebugExperience } from '@contentful/experiences-react';

<DebugExperience experience={experience} errors={experience.diagnostics} defaultOpen />;
```

It renders a native `<details>` element, so it collapses without JavaScript.

## Diagnostics

Diagnostics come from two stages:

| Stage        | When                                                              | Where                                                                         | Covers                                                                                                                      |
| ------------ | ----------------------------------------------------------------- | ----------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------- |
| Resolve time | Inside `fetchExperience` or `resolveExperience`, before rendering | `experience.diagnostics`, an array of `Error`s, empty when nothing went wrong | Malformed payload or slot, a node with no component reference, a failing `resolveData` function, an unresolved design token |
| Render time  | While the experience renders                                      | The debug panel                                                               | An unregistered component or experience template, a component that throws                                                   |

Each diagnostic is an `Error` whose message names the node, component, or slot involved. When it wraps a caught error, such as from a component or a `resolveData` function, `cause` holds the original error and its stack trace.

`experience.diagnostics` holds `Error` objects, which don't survive JSON serialization. To send an experience from the server to the client, convert the diagnostics to messages first.

### Delivery diagnostics

`experience.deliveryDiagnostics` lists the fields the Experience Delivery API couldn't resolve, such as a content binding to a missing entry. Each record has a `fieldPath` and a `message`. The affected fields arrive as `null`, and the field is absent when the API reports no errors.

The messages come from the API and can contain private data. Show a generic partial-content warning or a count by default, keep the details out of automatic logs and client payloads, and inspect them explicitly when you investigate a problem. The debug panel doesn't include them.

## How each failure is handled

| Failure                                                  | What happens                                                                                                   | How to fix it                                                                        |
| -------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------ |
| The experience doesn't exist                             | `fetchExperience` throws `NotFoundError`                                                                       | Check the experience ID, space, and environment. Return your framework's 404.        |
| The request fails                                        | `fetchExperience` throws `ExperienceFetchError`, with the original error as `cause`                            | Check the token and host. Handle the error in your route.                            |
| The payload's `nodes` isn't an array                     | Warns and renders nothing                                                                                      | Check the payload. A hand-built experience must use arrays.                          |
| A slot isn't an array of nodes                           | Warns and renders the slot as empty                                                                            | Check the payload. A hand-built experience must use arrays.                          |
| A node has no component or experience template reference | Warns and drops the node and its children; siblings render                                                     | Check that the node's component or experience template still exists in Contentful.   |
| `resolveData` throws or rejects                          | Warns; the node renders without its resolved data, and other resolvers are unaffected                          | Fix the error, or catch it inside `resolveData` and return fallback props.           |
| A design token has no mapping                            | Warns; the raw token reaches the component                                                                     | Add the token ID to `resolveToken`.                                                  |
| A component ID isn't registered                          | Renders the missing-component fallback: a visible box in debug mode, nothing otherwise                         | Register the component in `components`. To change the fallback, use `renderUnknown`. |
| An experience template ID isn't registered               | Warns and renders the template's slot children without the template                                            | Register the template in `experienceTemplates`.                                      |
| A component throws while rendering                       | Isolates the node; siblings render. Renders the error fallback: a visible box in debug mode, nothing otherwise | Fix the component. To change the fallback, use `renderError`.                        |

## Custom fallbacks

You can pass your own fallbacks to the renderer for an unregistered component (`renderUnknown`) or a component that throws (`renderError`). Your fallback renders whether or not debug mode is on, so check `debug` yourself if you need to.

```tsx
import type { ComponentErrorProps, MissingComponentProps } from '@contentful/experiences-react';

function Unknown({ componentId, nodeId }: MissingComponentProps) {
  return <div data-unregistered={componentId}>Unregistered component {componentId}</div>;
}

function Failed({ componentId, message }: ComponentErrorProps) {
  return <div data-render-error={componentId}>{componentId} failed to render: {message}</div>;
}

<ServerExperienceRenderer
  experience={experience}
  config={experienceConfig}
  renderUnknown={Unknown}
  renderError={Failed}
/>;
```

`renderUnknown` receives `componentId` and `nodeId`. `renderError` also receives `message`. In Svelte, pass a Svelte component. In Angular, pass a component class.

## Server and client differences

The only way to detect a component that throws is by rendering it. Each framework's server renderer handles that differently:

| Framework | Server rendering                                                                   | Client rendering                          |
| --------- | ---------------------------------------------------------------------------------- | ----------------------------------------- |
| React     | Renders the error fallback. The diagnostic appears only after the client hydrates. | Catches the error with an error boundary. |
| Svelte    | Doesn't catch the error. A throw during server rendering fails the whole page.     | Catches the error.                        |
| Angular   | Catches the error the same way as on the client, and records the diagnostic.       | The same code path as the server.         |

* **React**: Check the debug panel on the client to see a diagnostic from server rendering.
* **Svelte and SvelteKit**: Add a [`handleError` hook](https://svelte.dev/docs/kit/hooks#Shared-hooks-handleError) to turn a server render failure into a controlled error response, and test your components' failure paths.
* **Angular**: A component that throws while it's created is isolated on both the server and the client.

A throw during a later re-render is caught in React and Svelte. In Angular, a throw from the adapter's own resolution step is caught and recovers on the next successful render, but a throw from inside your component on a later change detection pass isn't caught.

## Troubleshooting

| What you see                                        | What to check                                                                                                                                        |
| --------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
| A component renders nothing.                        | Turn on debug mode. A **Missing component** box means its ID isn't registered: add it to `components` under that key.                                |
| Content props are `null`.                           | Check `experience.deliveryDiagnostics` for fields the Experience Delivery API couldn't resolve, and the experience's content bindings in Contentful. |
| A design prop holds `{ type: 'DesignToken', ... }`. | Add a `resolveToken` mapping for that token ID.                                                                                                      |
| A component's resolved data is missing.             | Check `experience.diagnostics` for a failing `resolveData` function.                                                                                 |
| `fetchExperience` throws `NotFoundError`.           | Check the experience ID, space, and environment. An unpublished experience is available only with `preview: true`.                                   |
| An experience renders with no content.              | The experience has no published nodes, for example in this locale. Check the experience's `nodes` array.                                             |