Skip to content

🔧 [Refactor] Inconsistent Error Handling Patterns #411

@mahula

Description

@mahula

🔧 Refactor

Problem

The codebase has multiple inconsistent error handling patterns across different components and API layers, making it difficult to maintain, debug, and provide consistent user experience.

Current Error Handling Patterns Analysis

✅ GOOD PATTERNS (Established Standards)

1. Comprehensive API Error Handling (itemFunctions.ts)

const handleApiOperation = async (operation, toastId, successMessage) => {
  try {
    const data = await operation()
    toast.update(toastId, {
      render: successMessage,
      type: 'success',
      isLoading: false,
      autoClose: 5000,
    })
    return { success: true, data }
  } catch (error) {
    const errorMessage = error instanceof Error ? error.message : String(error)
    toast.update(toastId, {
      render: errorMessage,
      type: 'error',
      isLoading: false,
      autoClose: 5000,
      closeButton: true,
    })
    return { success: false }
  }
}

2. Authentication with toast.promise Pattern

// LoginPage.tsx, SignupPage.tsx, RequestPasswordPage.tsx
await toast.promise(login({ email, password }), {
  success: { render({ data }) { return `Hi ${data?.first_name}` } },
  error: { render({ data }) { return `${data as string}` } },
  pending: 'logging in ...',
})

3. Structured Error State Management (App.tsx)

const [loading, setLoading] = useState<boolean>(true)
const [error, setError] = useState<string | null>(null)

catch (error: any) {
  console.error('Failed to load map:', error)
  setError(
    typeof error === 'string' ? error :
    (error?.errors?.length > 0 ? error.errors[0]?.message : null) ||
    error?.message ||
    'Failed to connect to the server. Please check your connection and try again.'
  )
  setLoading(false)
}

❌ PROBLEMATIC PATTERNS (Inconsistent)

1. Silent Failures (Geographic Search)

// SearchControl.tsx
catch (error) {
  console.log(error)  // Only logging, no user feedback
}

// ReverseGeocoder.ts  
catch (error) {
  console.error('Error:', error)  // Only logging
  return ''  // Silent failure
}

2. Inconsistent Toast Error Handling

// ItemViewPopup.tsx
catch (error) {
  toast.error(error.toString())  // Basic toString()
}

// ItemFormPopup.tsx
catch (error) {
  toast.error(error instanceof Error ? error.message : String(error))  // Better
}

// SocialShareBar.tsx
catch (error: never) {
  toast.error('Fehler beim Kopieren des Links: ', error)  // Mixed language
}

3. Inconsistent API Error Processing

// itemsApi.ts - Good pattern
catch (error: any) {
  console.error(error)
  if (error.errors?.[0]?.message) {
    throw new Error(error.errors[0].message)
  } else {
    throw error
  }
}

// userApi.ts - Different pattern  
catch (error: any) {
  console.log(error)  // console.log vs console.error
  if (error.errors[0]?.message) throw error.errors[0].message
  else throw error
}

// refiBcnApi.ts - Another pattern
catch (error: any) {
  console.log(error)
  if (error.errors[0]?.message) throw error.errors[0].message
  else throw error
}

4. Missing Error Boundaries

  • No React Error Boundaries found in the codebase
  • No fallback UI for component crashes
  • No error recovery mechanisms for rendering errors

5. Inconsistent Loading State Management

// Some components use local loading state
const [loading, setLoading] = useState<boolean>(false)

// Others use toast.loading with manual updates
const toastId = toast.loading('Creating profile at location')

// Others use toast.promise (best practice)
await toast.promise(operation(), { pending, success, error })

6. Form Validation Inconsistencies

// Basic validation in ItemFormPopup.tsx
if (!itemName) {
  toast.error('Name must be defined')
  return false
}

// HTML validation in TextInput.tsx
<input required={required} pattern={pattern} />

// No centralized validation utilities

Impact on Codebase

Maintainability Issues

  • Code Duplication: Similar error handling logic repeated across files
  • Inconsistent Debugging: Different logging patterns make issues harder to trace
  • Mixed Standards: New developers unsure which pattern to follow

User Experience Issues

  • Inconsistent Feedback: Some errors show toasts, others fail silently
  • Mixed Languages: Error messages in different languages
  • No Recovery Options: Users can't retry failed operations consistently

Development Issues

  • Testing Complexity: Different error patterns require different test approaches
  • Error Tracking: Inconsistent error reporting makes monitoring difficult
  • Onboarding Friction: New developers need to learn multiple patterns

Refactoring Goals

1. Standardize Error Handling Utilities

  • Create reusable error handling functions
  • Establish consistent logging patterns
  • Implement standard error message formatting

2. Implement Error Boundaries

  • Add React Error Boundaries for component crash recovery
  • Create fallback UI components
  • Implement error reporting mechanisms

3. Unify Loading State Patterns

  • Standardize on toast.promise for async operations
  • Create consistent loading state management
  • Implement proper loading indicators

4. Centralize Form Validation

  • Create reusable validation utilities
  • Implement consistent validation error display
  • Add proper form error recovery

Refactoring Plan

Phase 1: Create Standard Utilities

// utils/errorHandling.ts
export const handleApiError = (error: unknown): string => {
  if (error instanceof Error) return error.message
  if (typeof error === 'string') return error
  if (error?.errors?.[0]?.message) return error.errors[0].message
  return 'An unexpected error occurred'
}

export const logError = (context: string, error: unknown) => {
  console.error(`[${context}]`, error)
  // Add error reporting service integration
}

Phase 2: Implement Error Boundaries

// components/ErrorBoundary.tsx
class ErrorBoundary extends React.Component {
  // Standard error boundary implementation
}

Phase 3: Standardize Existing Patterns

  • Update all API classes to use consistent error handling
  • Replace silent failures with proper user feedback
  • Unify toast notification patterns

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions