SyntaxStudy
Sign Up
Swift Error Protocol and Custom Errors
Swift Beginner 1 min read

Error Protocol and Custom Errors

Swift errors conform to the Error protocol (which itself conforms to Sendable). Custom error types are usually enumerations with associated values providing context about what went wrong. Throwing functions are marked throws and called with try. Errors propagate up the call stack until caught in a do-catch block. Functions marked rethrows only throw if their closure argument throws. LocalizedError provides user-facing messages: errorDescription, failureReason, recoverySuggestion, and helpAnchor.
Example
import Foundation

// Custom error with LocalizedError
enum ValidationError: LocalizedError {
    case emptyField(name: String)
    case tooShort(field: String, minimum: Int)
    case invalidFormat(field: String, expected: String)

    var errorDescription: String? {
        switch self {
        case .emptyField(let name):
            return "\(name) cannot be empty"
        case .tooShort(let field, let min):
            return "\(field) must be at least \(min) characters"
        case .invalidFormat(let field, let fmt):
            return "\(field) must match format: \(fmt)"
        }
    }

    var recoverySuggestion: String? {
        "Please correct the input and try again."
    }
}

struct RegistrationForm {
    var username: String
    var email: String
    var password: String

    func validate() throws {
        guard !username.isEmpty else { throw ValidationError.emptyField(name: "Username") }
        guard username.count >= 3 else { throw ValidationError.tooShort(field: "Username", minimum: 3) }
        guard email.contains("@") else { throw ValidationError.invalidFormat(field: "Email", expected: "user@domain.com") }
        guard password.count >= 8 else { throw ValidationError.tooShort(field: "Password", minimum: 8) }
    }
}

do {
    let form = RegistrationForm(username: "ab", email: "not-an-email", password: "short")
    try form.validate()
} catch let error as ValidationError {
    print(error.errorDescription ?? "Unknown error")
    print(error.recoverySuggestion ?? "")
}