package errors import ( "fmt" "strings" ) // ConnectionError represents SSH connection errors with helpful hints type ConnectionError struct { Type string // "auth", "network", "timeout", "config", "unknown" Message string Details string Hints []string } // Error implements the error interface func (e *ConnectionError) Error() string { return fmt.Sprintf("Connection Error (%s): %s\nDetails: %s", e.Type, e.Message, e.Details) } // NewConnectionError creates a new ConnectionError func NewConnectionError(errType, message, details string, hints []string) *ConnectionError { return &ConnectionError{ Type: errType, Message: message, Details: details, Hints: hints, } } // HandleSSHError processes SSH errors and returns user-friendly errors func HandleSSHError(err error) *ConnectionError { if err == nil { return nil } errStr := err.Error() switch { case strings.Contains(errStr, "connection refused"): return &ConnectionError{ Type: "network", Message: "Cannot connect to server", Details: errStr, Hints: []string{"Check if server is running", "Verify firewall rules", "Confirm hostname and port"}, } case strings.Contains(errStr, "authentication failed"), strings.Contains(errStr, "unable to authenticate"): return &ConnectionError{ Type: "auth", Message: "Authentication failed", Details: errStr, Hints: []string{"Verify username and password", "Check SSH key is loaded", "Test with native SSH client"}, } case strings.Contains(errStr, "timeout"), strings.Contains(errStr, "timed out"): return &ConnectionError{ Type: "timeout", Message: "Connection timeout", Details: errStr, Hints: []string{"Check network connectivity", "Try increasing timeout", "Verify server is reachable"}, } case strings.Contains(errStr, "no such host"), strings.Contains(errStr, "hostname"): return &ConnectionError{ Type: "config", Message: "Invalid hostname", Details: errStr, Hints: []string{"Verify hostname spelling", "Check DNS resolution", "Try IP address instead"}, } case strings.Contains(errStr, "permission denied"): return &ConnectionError{ Type: "auth", Message: "Permission denied", Details: errStr, Hints: []string{"Check user permissions on server", "Verify account is not locked", "Check authentication method"}, } default: return &ConnectionError{ Type: "unknown", Message: "Connection failed", Details: errStr, Hints: []string{"Check host configuration", "Verify network settings", "Test with standard SSH client"}, } } } // FormatConnectionError formats connection error for user-friendly display func FormatConnectionError(err *ConnectionError) string { var output strings.Builder output.WriteString(fmt.Sprintf("❌ Connection Error: %s\n\n", err.Message)) output.WriteString(fmt.Sprintf("Details: %s\n\n", err.Details)) if len(err.Hints) > 0 { output.WriteString("Possible solutions:\n") for i, hint := range err.Hints { output.WriteString(fmt.Sprintf(" %d. %s\n", i+1, hint)) } } return output.String() }