Add error boundaries to your custom component
Error boundaries catch runtime rendering errors inside React components and prevent them from crashing the entire page. When an error occurs, the boundary renders a fallback component instead of letting the error propagate.
The C3 Agentic AI Platform supports two ways to implement error boundaries:
- Use UiSdlErrorBoundary in your JSON metadata
- Build a reusable error boundary in TypeScript and apply it manually
Wrap a component in JSON using UiSdlErrorBoundary
Use UiSdlErrorBoundary to catch rendering errors and display a fallback UI when something goes wrong. Wrap only the component that might fail—not the entire layout or page.
// {package}/ui/c3/meta/WindTurbine.ErrorBoundary.json
{
"type": "UiSdlErrorBoundary", // Error boundary component provided by the platform
"children": [
{
"id": "WindTurbine.CustomComponentWithError" // Component that might throw an error
}
],
"fallbackComponent": {
"id": "WindTurbine.FallbackComponent" // Component to show if an error is caught
}
}In this example:
- The platform renders
CustomComponentWithError - If that component throws an error during render, the boundary displays
FallbackComponentinstead
Create a failing component for testing
Use this component to simulate a rendering failure and test your error boundary setup.
// {package}/ui/c3/src/customInstances/WindTurbine.CustomComponentWithError.tsx
import * as React from 'react';
const CustomComponentWithError = () => {
// Simulate a failure by throwing during render
throw new Error('This error is for error boundary demo purpose.');
};
export default CustomComponentWithError;You can remove the throw statement once you've confirmed the error boundary behaves as expected.
Create the fallback component
The fallback component shows a user-friendly message when the boundary catches an error. You can use a shared UI component like CustomErrorBoundary for consistency across the app.
// {package}/ui/c3/src/customInstances/WindTurbine.FallbackComponent.tsx
import * as React from 'react';
// Reusable platform error screen
import CustomErrorBoundary from '@c3/app/ui/src/errorPages/CustomErrorBoundary';
const FallbackComponent = () => (
<CustomErrorBoundary
errorMessage="This is a fallback component for error boundary." // Displayed in large text
errorDescription="Please check console for error details." // Optional supporting text
/>
);
export default FallbackComponent;Use this component anywhere you want to show a standard fallback message.
Build a reusable error boundary component
The CustomErrorBoundary component defines the layout and logic for your fallback UI. It displays a placeholder logo, optional image, error message, status code, and description.
// {package}/ui/c3/src/errorPages/CustomErrorBoundary.tsx
import * as React from 'react';
// Hook to resolve translated text (optional)
import { useTranslate } from '@c3/sdl-react/hooks/useTranslate';
// Helper to clean image URLs
import { getUrlWithoutStartSlash } from '@c3/sdl-react/reactComponents/menu/navMenuHelper';
// Global error styles
import '@c3/css-library/components/_error.scss';
interface ErrorComponentProps {
imageSrc?: string; // Optional image to display
statusCode?: string; // Optional HTTP-style status (e.g., 500, 404)
errorMessage?: string; // Main error message text
errorDescription?: string; // Supporting description below the error message
}
const CustomErrorBoundary = (props: ErrorComponentProps) => {
const translate = useTranslate(props); // Enable translation for alt text
return (
<div className="c3-sdl-error-component">
<div className="c3-sdl-error-component-content">
{props.imageSrc ? (
// Show a custom image if provided
<img
src={getUrlWithoutStartSlash(props.imageSrc)} // Normalize image URL
alt={translate({ key: 'CustomErrorBoundary.altText' })} // Alt text for accessibility
className="c3-sdl-error-component-image"
/>
) : (
// If no image provided, render a placeholder
<div data-testid="logo-placeholder" className="logo logo-placeholder" />
)}
{/* Render status code if provided */}
{props.statusCode && (
<h1 className="c3-sdl-error-component-status-code">{props.statusCode}</h1>
)}
{/* Render error message if provided */}
{props.errorMessage && (
<h2 className="c3-sdl-error-component-error-message">{props.errorMessage}</h2>
)}
{/* Render description if provided */}
{props.errorDescription && (
<p className="c3-sdl-error-component-error-description">{props.errorDescription}</p>
)}
</div>
</div>
);
};
export default CustomErrorBoundary;This pattern helps you reuse a single fallback component across charts, forms, detail pages, and more.
Show a static error screen without a boundary
You don’t need a boundary in every case. Sometimes you want to show a custom error page directly. This example renders a static fallback without trying to wrap any children.
// {package}/ui/c3/src/customInstances/WindTurbine.CustomErrorComponent.tsx
import * as React from 'react';
import CustomErrorBoundary from '@c3/app/ui/src/errorPages/CustomErrorBoundary';
const CustomErrorComponent = () => (
<CustomErrorBoundary
imageSrc="" // No image
statusCode="000001" // Example status
errorMessage="This is not an actual error." // Custom message
errorDescription="This is a demo page showing the error component." // Description text
/>
);
export default CustomErrorComponent;Use this approach to show error messages for manual validation, unsupported features, or offline states.
When to wrap a component in an error boundary
Error boundaries catch unexpected render-time failures and prevent them from crashing the entire UI tree. Use boundaries to isolate unstable components and keep the rest of the app running.
Wrap components that:
- Render charts or graphs (ECharts, D3, Highcharts)
- Parse data that might be malformed
- Access props from application state or route context
- Use third-party UI libraries or custom layouts
- Perform conditional rendering that may throw
Avoid wrapping:
- The entire page layout
- Components that never touch dynamic data or external libraries