← thecodex.expert · The Codex Family of Knowledge
Swift

Error Handling

Swift’s throws sits deliberately between Java’s checked exceptions and Kotlin’s total absence of them — a function must genuinely declare it can throw, and by default doesn't have to specify exactly which errors, though Swift 6 added an opt-in way to do exactly that.

Swift 6 throws is required; untyped by default, typed since Swift 6 Last verified:
Canonical Definition

Errors are typically modeled as an enum conforming to the Error protocol, with cases representing each distinct failure. A function that might throw is marked throws in its signature — REQUIRED, and compiler-enforced, unlike Kotlin's total absence of any such declaration — though unlike Java's checked exceptions, plain throws doesn't specify which Error types are possible, only that some error might occur — Swift 6's typed throws (throws(SomeError), SE-0413) is the opt-in exception: it lets a function declare the single specific error type it throws, giving catch blocks a concretely-typed error instead of the general Error protocol. Callers must handle this explicitly: do/catch with try inside the do block, try? converting a thrown error into nil instead of propagating it, or try! asserting no error will occur (crashing at runtime if that assertion turns out wrong).

Defining errors and a throwing function

throws is REQUIRED on divide's signature — omitting it while the body still contains a throw statement is a compile error, unlike Kotlin, where no such declaration exists at all.

Swiftthrowing_function.swift
enum MathError: Error {
    case divideByZero
}

func divide(_ a: Int, by b: Int) throws -> Int {   // 'throws' is REQUIRED here
    if b == 0 {
        throw MathError.divideByZero
    }
    return a / b
}

do/catch: handling the thrown error

try marks each call inside the do block that might throw — execution jumps to a matching catch the instant an error is actually thrown, exactly like a typical try/catch elsewhere.

Swiftdo_catch.swift
do {
    let result = try divide(10, by: 0)
    print(result)
} catch MathError.divideByZero {
    print("Cannot divide by zero")
} catch {
    print("Unknown error: \(error)")
}

try? and try!: two alternatives to do/catch

try? converts a thrown error into nil instead of propagating it — genuinely useful when the caller only cares whether it succeeded, not why it failed; try! is a much stronger assertion, crashing the program at runtime if an error actually occurs.

Swifttry_variants.swift
let result1 = try? divide(10, by: 0)   // nil — the error becomes an Optional instead
print(result1)   // nil

// let result2 = try! divide(10, by: 0)   // CRASHES at runtime — asserting no error will happen

Sources

1
Apple / Swift.org. The Swift Programming Language, "Error Handling," docs.swift.org/swift-book.