# Error Display Strategy **Date**: 2025-01-27 **Action**: 3.1.1.5 - Create error display strategy document **Status**: ✅ Complete ## Overview This document defines the strategy for when to use `toast.error()` vs `ErrorDisplay` component for error presentation across the application. This strategy ensures consistent, user-friendly error handling while maintaining appropriate UX patterns for different error types. ## Core Principles 1. **Persistent errors** → Use `ErrorDisplay` (user needs to see and potentially act on the error) 2. **Transient errors** → Use `toast.error()` (quick feedback for temporary actions) 3. **Form validation** → Keep inline validation errors (field-level feedback) 4. **Critical errors** → Use `ErrorDisplay` with retry capability 5. **User action errors** → Use `ErrorDisplay` banner (dismissible, contextual) ## Decision Tree ``` Is the error related to form validation? ├─ YES → Use inline validation error (text-red-500, keep existing pattern) └─ NO → Continue Is the error from a query (data fetching)? ├─ YES → Use ErrorDisplay card/inline variant with retry └─ NO → Continue Is the error from a mutation (data update)? ├─ YES → Use ErrorDisplay banner variant (dismissible) └─ NO → Continue Is the error from a quick action (copy link, quick toggle)? ├─ YES → Use toast.error() (transient feedback) └─ NO → Continue Is the error critical (network failure, auth failure, runtime crash)? ├─ YES → Use ErrorDisplay with appropriate variant and retry └─ NO → Use toast.error() as fallback ``` ## ErrorDisplay Usage Guidelines ### When to Use ErrorDisplay #### 1. Query Errors (Data Fetching) **Use**: `ErrorDisplay` card or inline variant **Variant**: `card` for page-level errors, `inline` for component-level errors **Features**: Retry button, error details (dev mode) **Examples**: - Failed to load tracks/library - Failed to load playlist details - Failed to load user profile - Failed to load marketplace items ```tsx { isError && ( refetch()} /> ); } ``` #### 2. Mutation Errors (Data Updates) **Use**: `ErrorDisplay` banner variant **Variant**: `banner` (dismissible, appears at top of page/content) **Features**: Dismiss button, contextual error message **Examples**: - Failed to add track to playlist - Failed to update profile - Failed to delete resource - Failed to share resource ```tsx { mutationError && ( setMutationError(null)} /> ); } ``` #### 3. Network Errors (API Failures) **Use**: `ErrorDisplay` banner variant **Variant**: `banner` or `card` depending on context **Features**: Retry button, network-specific messaging **Examples**: - Connection timeout - Server unavailable - Network request failed ```tsx retryRequest()} /> ``` #### 4. Runtime Errors (Component Crashes) **Use**: `ErrorDisplay` in ErrorBoundary fallback **Variant**: `card` or `modal` **Features**: Error details, reload page action **Examples**: - Component render error - Unhandled exception - React error boundary catch ```tsx window.location.reload() }, ]} /> } > {children} ``` #### 5. Auth Errors (Authentication Failures) **Use**: `ErrorDisplay` inline variant **Variant**: `inline` **Features**: Contextual auth error message **Examples**: - Login failed - Session expired - Unauthorized access ```tsx ``` #### 6. Player Errors (Audio Playback) **Use**: `ErrorDisplay` card variant **Variant**: `card` **Features**: Retry button, error type detection **Examples**: - Audio decode error - Network error during playback - Source file not found ```tsx retryPlayback()} /> ``` ### When NOT to Use ErrorDisplay #### 1. Form Validation Errors **Use**: Inline validation errors (existing pattern) **Reason**: Field-level feedback is more appropriate **Pattern**: Keep existing `text-red-500` inline errors ```tsx // ✅ Keep this pattern { errors.field && (

{errors.field.message}

); } ``` #### 2. Quick Action Errors (Transient) **Use**: `toast.error()` **Reason**: Quick feedback for temporary actions **Examples**: - Copy link to clipboard - Quick toggle actions - Temporary state changes ```tsx // ✅ Keep toast for quick actions try { await navigator.clipboard.writeText(link); toast.success('Link copied'); } catch { toast.error('Failed to copy link'); } ``` #### 3. Validation Messages (Non-Critical) **Use**: `toast.error()` or inline validation **Reason**: User input validation feedback **Examples**: - "Username is required" - "Please type DELETE to confirm" - "Cart is empty" ```tsx // ✅ Keep toast for validation messages if (!username) { toast.error('Username is required'); return; } ``` ## Variant Selection Guide ### `inline` Variant **Use when**: - Error is contextual to a specific component - Error appears within content flow - Error doesn't need to interrupt user flow **Examples**: - Form submission errors - Component-level query errors - Inline validation errors (if not using form validation pattern) ### `banner` Variant **Use when**: - Error affects page-level functionality - Error is dismissible - Error should be prominent but not blocking **Examples**: - Mutation errors (add/update/delete) - Network errors - Session expiration warnings ### `card` Variant **Use when**: - Error replaces main content - Error needs visual prominence - Error is part of content layout **Examples**: - Query errors (no data to show) - Player errors (replaces player UI) - Profile load errors ### `modal` Variant **Use when**: - Error is critical and blocking - User must acknowledge error - Error requires immediate attention **Examples**: - Critical system errors - Payment failures - Security violations ## Severity Selection Guide ### `error` Severity (Default) **Use when**: - Operation failed - Data cannot be loaded - Action cannot be completed **Visual**: Red colors, AlertCircle icon ### `warning` Severity **Use when**: - Operation partially succeeded - Warning that doesn't block functionality - User should be aware but can continue **Visual**: Yellow/gold colors, AlertTriangle icon ### `info` Severity **Use when**: - Informational message - Non-critical notification - Helpful context **Visual**: Cyan colors, Info icon ## Migration Strategy ### Phase 1: Query Errors (HIGH Priority) 1. Replace query error displays with ErrorDisplay card variant 2. Add retry functionality 3. Files: LibraryPage ✅, TrackDetailPage, MarketplaceHome, RolesPage, SettingsPage ### Phase 2: Mutation Errors (MEDIUM Priority) 1. Replace mutation toast.errors with ErrorDisplay banner variant 2. Add dismiss functionality 3. Files: All feature files with mutations ### Phase 3: Component Errors (MEDIUM Priority) 1. Replace PlayerError with ErrorDisplay card variant 2. Replace AuthErrorMessage with ErrorDisplay inline variant 3. Update ErrorBoundary fallback UI ### Phase 4: Network Errors (HIGH Priority) 1. Replace API client toast.errors with ErrorDisplay banner 2. Add retry functionality 3. File: api/client.ts ### Phase 5: Keep Toast for Transient Actions (LOW Priority) 1. Keep toast.error() for copy link, quick actions 2. Document exceptions 3. No changes needed ## Code Examples ### Query Error Pattern ```tsx const { data, isError, error, refetch } = useQuery({ queryKey: ['tracks'], queryFn: fetchTracks, }); return ( <> {isError ? ( refetch()} /> ) : ( )} ); ``` ### Mutation Error Pattern ```tsx const [mutationError, setMutationError] = useState(null); const handleMutation = async () => { try { setMutationError(null); await mutateAsync(data); toast.success('Success'); } catch (error) { const apiError = parseApiError(error); setMutationError(new Error(apiError.message)); } }; return ( <> {mutationError && ( setMutationError(null)} /> )}
); ``` ### Form Validation Pattern (Keep) ```tsx // ✅ Keep existing pattern for form validation ``` ### Quick Action Pattern (Keep Toast) ```tsx // ✅ Keep toast for quick actions const handleCopyLink = async () => { try { await navigator.clipboard.writeText(link); toast.success('Link copied'); } catch { toast.error('Failed to copy link'); } }; ``` ## Accessibility Considerations ### ErrorDisplay Component - ✅ ARIA `role="alert"` and `aria-live="polite"` - ✅ Keyboard navigation for retry/dismiss buttons - ✅ Screen reader announcements - ✅ Focus management ### Toast Notifications - ✅ ARIA live regions (handled by toast library) - ✅ Auto-dismiss with appropriate timing - ✅ Keyboard accessible ### Form Validation - ✅ Inline errors associated with form fields - ✅ ARIA `aria-invalid` and `aria-describedby` - ✅ Screen reader announcements ## Testing Strategy 1. **Query Errors**: Test retry functionality 2. **Mutation Errors**: Test dismiss functionality 3. **Network Errors**: Test retry and offline handling 4. **Form Validation**: Test inline error display 5. **Toast Errors**: Test transient error display ## Rollback Plan If ErrorDisplay causes issues: 1. Revert to toast.error() for affected areas 2. Keep ErrorDisplay for query errors (most critical) 3. Gradually reintroduce ErrorDisplay for mutations ## References - [ErrorDisplay Component API](./ERROR_DISPLAY_COMPONENT_API.md) - [Error Display Patterns Audit](../../docs/ERROR_DISPLAY_PATTERNS_AUDIT.md) - [Error Messages Utility](../../utils/errorMessages.ts) - [API Error Handler](../../utils/apiErrorHandler.ts)