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:
With debug mode on, the SDK:
- Logs the fetch, the raw payload, the resolution steps, and the time each
resolveDatafunction 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:
It renders a native <details> element, so it collapses without JavaScript.
Diagnostics
Diagnostics come from two stages:
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
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.
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:
- React: Check the debug panel on the client to see a diagnostic from server rendering.
- Svelte and SvelteKit: Add a
handleErrorhook 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.