Error Boundaries
Overview
ErrorBoundary catches exceptions thrown during component rendering and replaces the failed subtree with a fallback UI, preventing a single error from crashing the entire application. GlobalErrorHandler provides application-wide unhandled error capture for cross-cutting concerns such as analytics and telemetry reporting.
Key Concepts
ErrorBoundarywraps an array of child components. If any child'srender()throws,ErrorBoundaryrecords the error and renders a fallback instead.DefaultErrorFallbackis the built-in fallback component used when no custom fallback is provided; it renders a styled error card with a page-refresh button.GlobalErrorHandleris a singleton that captures bothwindow.errorevents and unhandled promise rejections, then notifies all registered listeners.ErrorInfodescribes where and how an error occurred: the component stack, the boundary that caught it, and an optional error ID.
API Reference
ErrorInfo
interface ErrorInfo {
componentStack: string; // stack trace or location string
errorBoundary?: string; // name of the boundary that caught the error
errorId?: string; // optional unique ID for correlation
}
ErrorBoundary
class ErrorBoundary {
constructor(children: Component[], fallbackComponent?: Component)
render(): string // renders children or fallback
resetError(): void // clears error state; next render retries children
getError(): Error | null
getErrorInfo(): ErrorInfo | null
}
GlobalErrorHandler
class GlobalErrorHandler {
static getInstance(): GlobalErrorHandler
setupGlobalHandlers(): void // attaches window.onerror and unhandledrejection
handleError(error: Error, errorInfo?: ErrorInfo): void
addErrorListener(
listener: (error: Error, errorInfo?: ErrorInfo) => void
): () => void // returns unsubscribe function
}
useErrorHandler
function useErrorHandler(): {
handleError: (error: Error, errorInfo?: ErrorInfo) => void;
addErrorListener: GlobalErrorHandler['addErrorListener'];
}
Basic Usage
import { ErrorBoundary, DefaultErrorFallback, GlobalErrorHandler } from '@tagna/udiot';
// Wrap components in an error boundary with a custom fallback
const fallback = new DefaultErrorFallback();
const boundary = new ErrorBoundary([new UserProfileComponent(), new ActivityFeedComponent()], fallback);
// Render — catches any thrown errors
const html = boundary.render();
// Reset after user acknowledges an error (e.g., after a retry button click)
boundary.resetError();
Common Patterns
Setting up global error reporting
import { GlobalErrorHandler } from '@tagna/udiot';
const handler = GlobalErrorHandler.getInstance();
handler.setupGlobalHandlers(); // capture window errors and unhandled rejections
// Forward to your telemetry system
handler.addErrorListener((error, errorInfo) => {
myTelemetryClient.captureException(error, {
extra: { componentStack: errorInfo?.componentStack },
});
});
Custom fallback component
import { ErrorBoundary } from '@tagna/udiot';
class ServiceUnavailableFallback {
render(): string {
return `
<div class="error-fallback">
<h2>Service temporarily unavailable</h2>
<p>Our team has been notified. Please try again in a few minutes.</p>
</div>
`;
}
}
const boundary = new ErrorBoundary(
[new PaymentWidget()],
new ServiceUnavailableFallback()
);
Manual error capture in middleware
Use a public pipeline handler and its error-result contract instead of the
internal middleware decorators. For example, call an application-owned reporter
inside a handler's try/catch and rethrow if the pipeline should record failure.
The caller must still inspect the returned success and error fields.
Browser error boundaries and global browser listeners are not server HTTP error handlers. Use the server adapter for HTTP responses.
Integration Notes
ErrorBoundaryis designed for component trees that implement arender(): stringinterface. It is not a decorator — instantiate it programmatically and include it in your render hierarchy.GlobalErrorHandler.setupGlobalHandlers()requires a browser environment (window). Call it once at application startup; calling it multiple times adds duplicate listeners.addErrorListenerreturns an unsubscribe function. Store and call it to clean up listeners (important in long-running server environments or tests).- Integrate with telemetry through an error listener; the internal
AILoggeddecorator is not a public root export.
Pitfalls
ErrorBoundary.resetError()only clears the boundary's internal state. If the root cause of the error is not fixed, the nextrender()call will catch it again immediately.GlobalErrorHandler.handleError()logs to the framework logger and then calls listeners. It does not suppress the error — unhandled promise rejections are still rejected.ErrorBoundarycatches errors thrown synchronously fromrender(). Async errors (e.g., insidesetTimeoutorfetch) are not caught; useGlobalErrorHandlerfor those.DefaultErrorFallbackrenders awindow.location.reload()button. In server-side rendering this produces non-functional markup; provide a custom fallback without browser-specific behavior.