Skip to main content

Error Handling & Validation

Status: ✅ Complete
Last Updated: 2026-01-18

Overview​

Complete error handling and validation system with centralized error handling middleware, consistent input validation, and comprehensive frontend error handling utilities.

Implementation Details​

Backend Error Handling​

  • ✅ Centralized error handling middleware
  • ✅ Custom error classes (AppError, ValidationError, NotFoundError, UnauthorizedError, ForbiddenError, ConflictError)
  • ✅ Enhanced error handler that handles Zod errors, Prisma errors, and generic errors
  • ✅ Route handler wrapper (asyncHandler) for automatic error catching
  • ✅ Comprehensive tests (33 tests passing)

Backend Validation​

  • ✅ Input validation consistency
  • ✅ Validation utility functions created (validateRequest, validateBody, validateParams, validateQuery) for consistent Zod validation across routes
  • ✅ Reduces boilerplate
  • ✅ Comprehensive tests (17 tests passing)

Frontend Error Handling​

  • ✅ Global error boundary (ErrorBoundary component created with error recovery UI, integrated into App.tsx)
  • ✅ Error recovery
  • ✅ Comprehensive tests (9 tests passing)

Frontend Error Handling Utilities (2026-01-18)​

  • ✅ Centralized error handling utility (errorHandler.ts)

    • Error message extraction from various error types
    • Error code extraction and mapping
    • Network error detection
    • Retryable error detection
    • User-friendly error message generation
    • API response error handling
    • Fetch error handling
    • Comprehensive tests (29 tests passing)
  • ✅ Error logging utility (errorLogger.ts)

    • Console-based logger for development
    • Production logger with extensible architecture (ready for Sentry/LogRocket integration)
    • Context-aware error logging
    • Warning and info logging support
    • Comprehensive tests (7 tests passing)
  • ✅ Enhanced API utility (api.ts)

    • Automatic retry logic for retryable errors (network errors, 5xx status codes)
    • Configurable retry options (max retries, delay, retryable status codes)
    • Better error handling for non-JSON responses
    • Improved network error detection and handling
    • Stale token detection and automatic redirect
  • ✅ useErrorHandler hook (useErrorHandler.tsx)

    • React hook for consistent error handling in components
    • Automatic toast notification integration
    • Error logging with component context
    • executeWithErrorHandling utility for async operations
    • Comprehensive tests (9 tests passing)
  • ✅ Enhanced ErrorBoundary

    • Integrated with centralized error handling
    • Automatic error logging with context
    • Development/production error display

Key Features​

Error Message Handling​

  • Automatic extraction of error messages from Error instances, strings, and objects
  • User-friendly message generation with fallbacks
  • Custom message support
  • Technical error filtering (stack traces, etc.)

Retry Logic​

  • Automatic retries for network errors and server errors (5xx)
  • Exponential backoff (configurable delay)
  • Configurable max retries per request
  • Skip retry option for non-retryable operations

Error Logging​

  • Context-aware logging (component, action, endpoint, etc.)
  • Development vs. production logging strategies
  • Extensible architecture for error tracking service integration
  • Automatic timestamp and environment context

Component Integration​

  • useErrorHandler hook for easy error handling in components
  • Automatic toast notifications
  • Error context tracking
  • Async operation error handling wrapper

Usage Examples​

Using useErrorHandler Hook​

import { useErrorHandler } from '../utils/useErrorHandler';

function MyComponent() {
const { handleError, handleApiError, executeWithErrorHandling } = useErrorHandler();

async function loadData() {
const response = await api.get('/data');
const error = handleApiError(response, {
componentName: 'MyComponent',
actionName: 'loadData',
});
if (error) return;
// Use response.data
}

async function saveData() {
await executeWithErrorHandling(
async () => {
const response = await api.post('/data', data);
if (!response.ok) throw new Error(response.error?.message);
},
{
componentName: 'MyComponent',
actionName: 'saveData',
customMessage: 'Failed to save data',
}
);
}
}

Direct Error Handling​

import { handleError, ErrorCode } from '../utils/errorHandler';
import { logError } from '../utils/errorLogger';

try {
// Some operation
} catch (error) {
const errorDetails = handleError(error, {
customMessage: 'Custom error message',
});
logError(errorDetails, {
component: 'MyComponent',
action: 'operation',
});
}

API Retry Configuration​

// Automatic retry (default: 2 retries for network/server errors)
const response = await api.get('/data');

// Custom retry configuration
const response = await api.get('/data', {
maxRetries: 3,
retryDelay: 2000,
retryOnNetworkError: true,
});

// Skip retry
const response = await api.post('/data', data, {
skipRetry: true,
});

Testing​

All error handling utilities have comprehensive test coverage:

  • errorHandler.test.ts: 29 tests
  • errorLogger.test.ts: 7 tests
  • useErrorHandler.test.tsx: 9 tests

Total: 45 tests for frontend error handling utilities