// lib/core/utils/error_utils.dart /// Converts raw exceptions into user-friendly messages. /// Strips technical details (hostnames, ports, stack traces, exception chains) /// and returns a clean message safe to display in the UI. String userFriendlyError(Object e) { final raw = e.toString(); // Network / connectivity issues if (raw.contains('SocketException') || raw.contains('Connection refused') || raw.contains('Connection reset') || raw.contains('Network is unreachable') || raw.contains('No address associated') || raw.contains('Failed to fetch') || raw.contains('HandshakeException') || raw.contains('ClientException')) { return 'Unable to connect. Please check your internet connection and try again.'; } // Timeout if (raw.contains('TimeoutException') || raw.contains('timed out')) { return 'The request took too long. Please try again.'; } // Rate limited if (raw.contains('status 429') || raw.contains('throttled') || raw.contains('Too Many Requests')) { return 'Too many requests. Please wait a moment and try again.'; } // Auth expired / forbidden if (raw.contains('status 401') || raw.contains('Unauthorized')) { return 'Session expired. Please log in again.'; } if (raw.contains('status 403') || raw.contains('Forbidden')) { return 'You do not have permission to perform this action.'; } // Server error if (RegExp(r'status 5\d\d').hasMatch(raw)) { return 'Something went wrong on our end. Please try again later.'; } // Not found if (raw.contains('status 404') || raw.contains('Not Found')) { return 'The requested resource was not found.'; } // Strip Exception wrappers and nested chains for validation messages var cleaned = raw .replaceAll(RegExp(r'Exception:\s*'), '') .replaceAll(RegExp(r'Failed to \w+ \w+:\s*'), '') .replaceAll(RegExp(r'Network error:\s*'), '') .replaceAll(RegExp(r'Request failed \(status \d+\)\s*'), '') .trim(); // If the cleaned message is empty or still looks technical, use a generic fallback if (cleaned.isEmpty || cleaned.contains('errno') || cleaned.contains('address =') || cleaned.contains('port =') || cleaned.startsWith('{') || cleaned.startsWith('[')) { return 'Something went wrong. Please try again.'; } // Capitalize first letter if (cleaned.isNotEmpty) { cleaned = cleaned[0].toUpperCase() + cleaned.substring(1); } return cleaned; }