Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
4.8 KiB
ADR 006: Error Boundary with Dual Variants
Status: Accepted
Date: 2026-03-05
Deciders: Development Team
Context
The Sealed Secrets plugin registers components at two distinct integration points in Headlamp:
- Route-level: Full-page views (
SealedSecretList,SealingKeysView) registered viaregisterRoute - Section-level: Injected detail sections (
SecretDetailsSection) registered viaregisterDetailsViewSection
Each integration point has different error recovery requirements:
- Route-level errors typically stem from API connectivity issues (controller not found, RBAC misconfiguration). Users need troubleshooting guidance and a retry mechanism.
- Section-level errors are isolated failures within a host page. The error should be contained without disrupting the rest of the detail view. A simple reload is sufficient.
A single error boundary class cannot serve both needs because the error messaging, recovery actions, and visual treatment differ significantly.
Decision
Implement a BaseErrorBoundary abstract class with a renderError() template method, then derive two concrete variants:
ApiErrorBoundary: Used at route level. Displays connectivity troubleshooting guidance (check controller namespace, RBAC permissions, pod status) with a Retry button that resets the error state.GenericErrorBoundary: Used at section level. Displays a compact error message with a Reload button. Designed to fail gracefully without affecting the parent detail page.
Both variants use getDerivedStateFromError for error capture and expose a reset mechanism via setState({ hasError: false }).
abstract class BaseErrorBoundary extends React.Component<Props, State> {
static getDerivedStateFromError(error: Error): State {
return { hasError: true, error };
}
abstract renderError(error: Error): React.ReactNode;
render() {
if (this.state.hasError) {
return this.renderError(this.state.error);
}
return this.props.children;
}
}
Consequences
Positive
✅ Appropriate error recovery: Each integration point gets tailored error messages and recovery actions
✅ Fault isolation: Section-level errors don't crash the entire detail page
✅ Shared base class: Common error capture logic is defined once in BaseErrorBoundary
✅ Consistent with React patterns: Error boundaries are the recommended React mechanism for catching render errors
Negative
⚠️ Class components required: React error boundaries must be class components, breaking the otherwise all-functional-component convention
⚠️ Two components to maintain: Changes to error handling patterns must be applied to both variants
Mitigation
- The class component exception is documented and limited to
ErrorBoundary.tsx - Both variants share
BaseErrorBoundary, so common logic changes propagate automatically
Alternatives Considered
1. Single generic error boundary
Pros:
- Simpler — one component for all uses
- Less code to maintain
Cons:
- Cannot provide context-specific troubleshooting guidance
- Route-level errors need different recovery UX than section-level errors
- Generic messages are unhelpful for API connectivity issues
Rejected: The error recovery requirements differ too much between route and section contexts.
2. try/catch in each component
Pros:
- No class components needed
- Per-component error handling
Cons:
- Cannot catch render-phase errors (React limitation)
- Duplicated error handling logic across every component
- Inconsistent error UX
Rejected: React error boundaries are the only mechanism for catching render errors.
3. React error boundary library (react-error-boundary)
Pros:
- Functional component API via
ErrorBoundarywrapper - Built-in reset mechanisms
- Well-maintained
Cons:
- External dependency not available in plugin runtime
- Plugin cannot add npm dependencies beyond Headlamp peer dependencies
Rejected: Dependency constraint makes this infeasible.
Implementation
ApiErrorBoundarywrapsSealedSecretListandSealingKeysViewinindex.tsxGenericErrorBoundarywrapsSecretDetailsSectioninindex.tsx- Both are defined in
src/components/ErrorBoundary.tsx - Uses MUI
Alert,Box,Button,Typographyfor styled error display
References
Related ADRs
- ADR 005: Custom React Hooks — Hooks architecture that error boundaries wrap
Changelog
- 2026-03-05: Initial decision