Tech News
← Back to articles

Type-safe and user-friendly error handling in Swift 6

read original related products more articles

Learn how to implement user-friendly, type-safe error handling in Swift 6 with structured diagnostics and a hierarchical error model.

Swift 6 brings an exciting new feature to the language: typed throws. This change makes error handling in Swift much more type-safe, allowing us to define exactly what kinds of errors a function can throw. It’s a small change on the surface, but it opens the door to writing cleaner, more reliable code.

Now, you might be wondering — how do we actually use this in practice? The idea I’m going to share with you came up during a conversation with my wife. She came up with this user-friendly layered error message model, and I turned it into a technique we even ended up using in Toucan, our Swift-based static site generator at Binary Birds.

In this post, I’ll show you how this approach works and how you can use it to improve your own Swift projects.

A custom error protocol

First of all, I was never satisfied with the built-in LocalizedError protocol. Sure, its errorDescription property could be used as a user-facing error message, but sometimes it’s more like a riddle, alongside NSError’s domains and codes. Additionally, if we stick to the base Error protocol, it can cause naming convention issues, or you have to write Swift.Error , which is very inconvenient.

That’s the reason why I started to define my own protocol, using Error as a base protocol, but with some additional functionalities:

public protocol SystemError: Error { // 1. var logMessage: String { get } // 2. var userFriendlyMessage: String { get } // 3. var underlyingErrors: [Error] { get } // 4. func logMessageStack() -> String // 5. func lookup(_ errorType: T.Type) -> T? // 6. func lookup(_ t: (T) -> V?) -> V? }

Let me explain each point:

The log message used by developers to display the error. The user-facing error message for your end users. An array of underlying errors for structured error diagnostics. The backtrace for developers to easily access the error hierarchy. A lookup function to detect an error type in the stack. A helper to simplify the lookup process, mainly for enum cases.

... continue reading