Error Handling System
March 10, 2026 · View on GitHub
Technical documentation for the centralized error handling system in Debian Time Capsule.
Overview
The Error Handler provides centralized error management across the application. It captures, logs, and reports errors consistently with contextual information and severity-based handling.
Architecture
┌──────────────────────────────────────────────┐
│ Application Code │
├──────────────────────────────────────────────┤
│ errorHandler.wrapAsync() / wrapSync() │
├──────────────────────────────────────────────┤
│ Error Handler │
│ • Capture • Log • Notify • Store │
├──────────────────────────────────────────────┤
│ Logger EventBus CDEModal History │
└──────────────────────────────────────────────┘
Core Features
Global Error Capture
Automatically captures uncaught errors and unhandled promise rejections:
window.addEventListener('error', (event) => {
errorHandler.handleError(event.error, {
module: 'Global',
action: 'unhandled-error',
severity: ErrorSeverity.CRITICAL,
});
});
window.addEventListener('unhandledrejection', (event) => {
errorHandler.handleError(new Error(event.reason), {
module: 'Global',
action: 'unhandled-promise',
severity: ErrorSeverity.CRITICAL,
});
});
Severity Levels
enum ErrorSeverity {
LOW = 'low', // Logged only, no user notification
MEDIUM = 'medium', // Logged as warning
HIGH = 'high', // Logged + user notification
CRITICAL = 'critical', // Logged + user notification
}
Error Context
interface ErrorContext {
module: string; // Module name (e.g., 'FileManager')
action?: string; // Action being performed (e.g., 'saveFile')
data?: any; // Additional context data
severity?: ErrorSeverity; // Error severity (default: MEDIUM)
userMessage?: string; // User-friendly message
}
Error History
Maintains last 100 errors for debugging:
interface AppError {
id: string; // Unique error ID (UUID)
timestamp: number; // Unix timestamp
error: Error; // Original error object
context: ErrorContext; // Error context
stack?: string; // Stack trace
}
Implementation
Wrapper Functions
class ErrorHandler {
// Async wrapper
async wrapAsync<T>(fn: () => Promise<T>, context: ErrorContext): Promise<T | null> {
try {
return await fn();
} catch (error) {
this.handleError(error instanceof Error ? error : new Error(String(error)), context);
return null;
}
}
// Sync wrapper
wrapSync<T>(fn: () => T, context: ErrorContext): T | null {
try {
return fn();
} catch (error) {
this.handleError(error instanceof Error ? error : new Error(String(error)), context);
return null;
}
}
}
Error Processing
handleError(error: Error, context: ErrorContext): void {
const appError: AppError = {
id: crypto.randomUUID(),
timestamp: Date.now(),
error,
context: { severity: ErrorSeverity.MEDIUM, ...context },
stack: error.stack,
};
// 1. Store in history
this.errorHistory.push(appError);
if (this.errorHistory.length > 100) {
this.errorHistory.shift();
}
// 2. Log to console
this.logError(appError);
// 3. Emit event
this.eventBus?.emitSync(SystemEvent.ERROR_OCCURRED, appError);
// 4. Show user notification (HIGH/CRITICAL only)
if (context.severity === ErrorSeverity.HIGH || context.severity === ErrorSeverity.CRITICAL) {
this.showUserNotification(appError);
}
}
Usage
Basic Error Handling
import { errorHandler, ErrorSeverity } from '../core/error-handler';
// Wrap async function
const result = await errorHandler.wrapAsync(
async () => {
const data = await fetchData();
return processData(data);
},
{
module: 'DataLoader',
action: 'loadData',
severity: ErrorSeverity.HIGH,
}
);
// Wrap sync function
const result = errorHandler.wrapSync(
() => {
return complexCalculation();
},
{
module: 'Calculator',
action: 'calculate',
severity: ErrorSeverity.MEDIUM,
}
);
Manual Error Handling
try {
await riskyOperation();
} catch (error) {
errorHandler.handleError(error instanceof Error ? error : new Error(String(error)), {
module: 'MyModule',
action: 'riskyOperation',
data: { userId: 123 },
severity: ErrorSeverity.HIGH,
userMessage: 'Operation failed. Please try again.',
});
}
Event Subscription
import { eventBus, SystemEvent } from '../core';
eventBus.on(SystemEvent.ERROR_OCCURRED, (errorData: AppError) => {
// Send to analytics, log to server, etc.
console.log('Error occurred:', errorData);
});
Integration
Container Registration
// container.init.ts
import { errorHandler } from './error-handler';
container.registerInstance('errorHandler', errorHandler);
EventBus Integration
// container.init.ts
const eventBus = container.get<EventBus>('eventBus');
errorHandler.setEventBus(eventBus);
Current Integrations
The Error Handler is integrated with:
- Emacs: File save operations
- Lynx: External page fetching
- FileManager: Event subscriptions
- Desktop: Initialization
- Clipboard: Paste operations
- ShareConfig: Theme encoding/loading
- ShareThemeUI: Theme sharing
Debugging
Get Error History
import { errorHandler } from '../core/error-handler';
// Get all errors
const errors = errorHandler.getErrorHistory();
// Get recent errors
const recent = errorHandler.getRecentErrors(10);
Clear History
errorHandler.clearErrors();
Best Practices
1. Provide Context
// Good
errorHandler.handleError(error, {
module: 'FileManager',
action: 'saveFile',
data: { path: '/home/user/file.txt' },
severity: ErrorSeverity.HIGH,
userMessage: 'Failed to save file',
});
// Bad
errorHandler.handleError(error, { module: 'Unknown' });
2. Use Appropriate Severity
- LOW: Optional features, non-critical failures
- MEDIUM: Important but recoverable errors
- HIGH: Serious errors affecting functionality
- CRITICAL: Application-breaking errors
3. Provide User-Friendly Messages
// Good
userMessage: 'The file could not be found. It may have been moved or deleted.';
// Bad
userMessage: 'ENOENT: no such file or directory';
4. Use Wrapper Functions
// Preferred
await errorHandler.wrapAsync(() => operation(), context);
// Instead of
try {
await operation();
} catch (error) {
errorHandler.handleError(error, context);
}
Event Data Structure
// ERROR_OCCURRED event payload
interface AppError {
id: string; // Unique error ID
timestamp: number; // Unix timestamp
error: Error; // Original error object
context: ErrorContext; // Error context
stack?: string; // Stack trace
}