Skip to navigation

Errors and debugging

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. In Svelte, a component that throws during server rendering also fails the page. See 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:

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:

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:

StageWhenWhereCovers
Resolve timeInside fetchExperience or resolveExperience, before renderingexperience.diagnostics, an array of Errors, empty when nothing went wrongMalformed payload or slot, a node with no component reference, a failing resolveData function, an unresolved design token
Render timeWhile the experience rendersThe debug panelAn 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

FailureWhat happensHow to fix it
The experience doesn’t existfetchExperience throws NotFoundErrorCheck the experience ID, space, and environment. Return your framework’s 404.
The request failsfetchExperience throws ExperienceFetchError, with the original error as causeCheck the token and host. Handle the error in your route.
The payload’s nodes isn’t an arrayWarns and renders nothingCheck the payload. A hand-built experience must use arrays.
A slot isn’t an array of nodesWarns and renders the slot as emptyCheck the payload. A hand-built experience must use arrays.
A node has no component or experience template referenceWarns and drops the node and its children; siblings renderCheck that the node’s component or experience template still exists in Contentful.
resolveData throws or rejectsWarns; the node renders without its resolved data, and other resolvers are unaffectedFix the error, or catch it inside resolveData and return fallback props.
A design token has no mappingWarns; the raw token reaches the componentAdd the token ID to resolveToken.
A component ID isn’t registeredRenders the missing-component fallback: a visible box in debug mode, nothing otherwiseRegister the component in components. To change the fallback, use renderUnknown.
An experience template ID isn’t registeredWarns and renders the template’s slot children without the templateRegister the template in experienceTemplates.
A component throws while renderingIsolates the node; siblings render. Renders the error fallback: a visible box in debug mode, nothing otherwiseFix 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.

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:

FrameworkServer renderingClient rendering
ReactRenders the error fallback. The diagnostic appears only after the client hydrates.Catches the error with an error boundary.
SvelteDoesn’t catch the error. A throw during server rendering fails the whole page.Catches the error.
AngularCatches 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 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 seeWhat 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.