6.2 KiB
Centralized Error Handling Architecture
Project: KROW Workforce Mobile App
1. Executive Summary
We have implemented a Centralized Error Handling System that ensures the entire application (Staff & Client) handles errors consistently, reliably, and with full localization support.
Instead of writing error handling code in every single feature (which leads to bugs and inconsistent messages), we rely on a global safety net that catches Network Failures, Server Errors (500), Not Found Errors (404), and Business Logic Violations automatically.
Key Benefits
- Safety: The app never crashes due to unhandled API errors.
- Consistency: A network error looks the same in "Shifts" as it does in "billing".
- Localization: All error messages are automatically translated (English/Spanish).
- Speed: Developers can build features faster without worrying about
try/catchblocks.
Technical Excellence (Status Code Handling)
We don't just catch "errors"; we understand them. The system automatically categorizes and handles:
- 500 (Server Error): "Our servers are having a moment. Please try again."
- 404 (Not Found): "The resource you're looking for (Shift/Profile) is missing."
- 401 (Unauthorized): "Your session expired. Please log in again." (Auto-redirect)
- 403 (Forbidden): "You don't have permission to access this area."
- 503 (Unavailable): "Maintenance mode or overloaded. Back in a bit!"
2. Architecture Overview
The error handling flows through three distinct layers, ensuring separation of concerns:
graph TD
A[Data Layer / Repository] -->|Throws AppException| B[BLoC Layer / State Management]
B -->|Emits Error Key| C[UI Layer / Presentation]
subgraph "1. Data Layer (The Guard)"
A -- Captures Exceptions --> D[DataErrorHandler Mixin]
D -- Maps to --> E[NetworkException, ServerException, etc.]
end
subgraph "2. BLoC Layer (The Translator)"
B -- Uses --> F[BlocErrorHandler Mixin]
F -- Catches AppException --> G[converts to 'errors.category.type']
end
subgraph "3. UI Layer (The Messenger)"
C -- Calls --> H[translateErrorKey()]
H -- Returns --> I["Localized String (e.g. 'Sin conexión')"]
end
1. The Data Layer (The Guard)
- Role: Wraps all API calls.
- Mechanism: Catches raw errors (SocketException, FirebaseException) and converts them into domain-specific
AppExceptions(e.g.,NetworkException). - Location:
packages/data_connect/lib/src/mixins/data_error_handler.dart
2. The BLoC Layer (The Logic)
- Role: Manages state.
- Mechanism: Uses
handleErrorhelper to execute logic. If anAppExceptionbubbles up, it automatically emits a failure state with a Message Key (e.g.,errors.auth.session_expired). - Location:
packages/core/lib/src/presentation/mixins/bloc_error_handler.dart
3. The UI Layer (The Presenter)
- Role: Shows the message.
- Mechanism: Observes the state. When an error occurs, it passes the key to
translateErrorKey(key)which returns the user-friendly text from the active language file (e.g.,es.i18n.json). - Location:
packages/core_localization/lib/src/utils/error_translator.dart
3. Verified Features
The following features have been audited and are confirmed to use the Centralized Error Handler:
✅ Core Infrastructure
- Authentication (Login/Signup)
- Firebase Data Connect Integration
- Localization Engine
✅ Staff App Features
| Feature | Status | Notes |
|---|---|---|
| Shifts | ✅ | Handles availability, accept, history errors |
| Profile | ✅ | Personal info, experience, attire updates |
| Onboarding | ✅ | Tax forms (W4/I9), emergency contacts |
| Compliance | ✅ | Document uploads, certificate management |
| Financials | ✅ | Bank accounts, time cards, payments |
| Availability | ✅ | Weekly schedule blocking |
| Clock In | ✅ | Location/Time validation errors |
✅ Client App Features
| Feature | Status | Notes |
|---|---|---|
| Auth | ✅ | Login, Signup failures |
| Create Order | ✅ | Type selection, validation |
| View Orders | ✅ | Loading lists, filtering |
| Hubs | ✅ | NFC assignment errors |
| Billing | ✅ | Payment methods, invoicing |
| Coverage | ✅ | Dashboard metric loading |
4. How to Verify (Demo Script)
Test A: The "Tunnel" Test (Network)
- Open the app to the Shifts page.
- Toggle Airplane Mode ON.
- Pull to refresh the list.
- Result: App shows a gentle
snackbarerror: "No internet connection" (or Spanish equivalent). No Crash.
Test B: The "Duplicate Data" Test (Smart Validation)
- Log in on two devices with the same account (if possible) or simply use a known registered email.
- Go to the Sign Up page.
- Try to register a new account using that existing email.
- Result: App instantly displays specific, helpful feedback: "An account with this email already exists." instead of a generic failure.
- Why it matters: Proves the backend and frontend are synced to guide the user, not just block them.
Test C: The "Crash Proof" Test (The Safety Net)
- Scenario: Even if a developer introduces a bug (like a random exception) or the server returns a 500 status.
- Result: The app catches the unknown error, logs it internally, and shows a safe default message: "Something went wrong. Please try again."
- Why it matters: The app never crashes or closes unexpectedly, preserving user trust.
Test D: The "Language" Test (Localization)
- Trigger an error (like wrong password).
- Change phone language to Spanish.
- Trigger the same error.
- Result: Message automatically translates: "Correo electrónico o contraseña inválidos."
5. Code Locations (Reference)
- Exceptions:
packages/domain/lib/src/exceptions/app_exception.dart - Data Mixin:
packages/data_connect/lib/src/mixins/data_error_handler.dart - Bloc Mixin:
packages/core/lib/src/presentation/mixins/bloc_error_handler.dart - Translator:
packages/core_localization/lib/src/utils/error_translator.dart - Strings:
packages/core_localization/lib/src/l10n/*.i18n.json