Error Handling Architecture in ROAR
Overview
ROAR implements a comprehensive error handling strategy with specialized error classes organized in a hierarchical structure. This architecture ensures errors are properly captured, categorized, and reported throughout the system.
Error Class Hierarchy
The error handling system follows a hierarchical design that mirrors the application's architecture:
Key Components
Client-Level Errors
FirebaseClientError
: Base error for Firebase client operationsFirebaseImplementationError
: Errors during Firebase implementation setup
Repository-Level Errors
FirestoreRepositoryError
: Base class for all repository errors- Entity-specific repository errors:
Service-Level Errors
AdministrationServiceError
: Errors in administration service operationsIdentityProviderServiceError
: Errors in identity provider service operations
Error Handling Principles
1. Error Encapsulation
Each error class encapsulates both an error message and the original error object, allowing for complete context preservation while providing a clean public API.
Example:
class FirestoreRepositoryError extends Error {
protected error: any;
constructor(message: string, error?: any) {
super(message);
this.name = 'FirestoreRepositoryError';
this.error = error;
}
}
2. Specialized Error Types
Repository-specific error classes provide factory methods for creating standardized error instances for common error scenarios:
class FirestoreIdentityProviderRepositoryError extends FirestoreRepositoryError {
public getByProviderIdError(): FirestoreIdentityProviderRepositoryError {
return new FirestoreIdentityProviderRepositoryError(
'Error retrieving identity provider by provider ID'
);
}
public noProviderDataError(): FirestoreIdentityProviderRepositoryError {
return new FirestoreIdentityProviderRepositoryError(
'No provider data available'
);
}
}
3. Error Propagation
Errors are propagated up the call stack, with each layer adding relevant context:
- Repository Layer: Catches database errors and wraps them in repository-specific errors
- Service Layer: Catches repository errors and wraps them in service-specific errors
- Controller/Function Layer: Catches service errors and formats appropriate responses
Best Practices
- Specific Error Messages: Include actionable details in error messages
- Error Categorization: Use specialized error classes for different error types
- Error Context: Preserve original errors for debugging
- Consistent Error Handling: Follow the same pattern across the codebase
- Error Logging: Log errors at appropriate levels with context
Example Usage
try {
const result = await identityProviderRepository.getByProviderId(params);
return result;
} catch (error) {
if (error instanceof FirestoreRepositoryError) {
throw error;
}
throw new FirestoreIdentityProviderRepositoryError(
'Failed to get identity provider by ID',
error
);
}