Making error handling in Swift more intuitive and powerful with clearer messages, type safety, and user-friendly diagnostics.
Swift's error handling has several limitations that make it challenging to create robust, user-friendly applications:
- The
Error
protocol's confusing behavior withlocalizedDescription
- Hard-to-understand system error messages
- Limited type safety in error propagation
- Difficulties with error chain debugging (relevant for typed throws!)
- Challenges in collecting meaningful feedback from users
ErrorKit addresses these challenges with a suite of lightweight, interconnected features you can adopt progressively.
Throwable
fixes the confusion of Swift's Error
protocol by providing a clear, Swift-native approach to error handling:
enum NetworkError: Throwable {
case noConnectionToServer
case parsingFailed
var userFriendlyMessage: String {
switch self {
case .noConnectionToServer:
String(localized: "Unable to connect to the server.")
case .parsingFailed:
String(localized: "Data parsing failed.")
}
}
}
Now when catching this error, you'll see exactly what you expect:
"Unable to connect to the server."
For rapid development, you can use string raw values:
enum NetworkError: String, Throwable {
case noConnectionToServer = "Unable to connect to the server."
case parsingFailed = "Data parsing failed."
}
Get improved, user-friendly messages for ANY error, including system errors:
do {
let _ = try Data(contentsOf: url)
} catch {
// Better than localizedDescription, works with any error type
print(ErrorKit.userFriendlyMessage(for: error))
// "You are not connected to the Internet. Please check your connection."
}
These enhanced descriptions are community-provided and fully localized mappings of common system errors to clearer, more actionable messages.
Read more about Enhanced Error Descriptions →
Swift 6 introduces typed throws (throws(ErrorType)
), bringing compile-time type checking to error handling. ErrorKit makes this powerful feature practical with solutions for its biggest challenges:
The Catching
protocol solves the biggest problem with error handling: nested errors.
enum ProfileError: Throwable, Catching {
case validationFailed(field: String)
case caught(Error) // Single case handles all nested errors!
var userFriendlyMessage: String { /* ... */ }
}
struct ProfileRepository {
func loadProfile(id: String) throws(ProfileError) -> UserProfile {
// Regular error throwing for validation
guard id.isValidFormat else {
throw ProfileError.validationFailed(field: "id")
}
// Automatically wrap any database or file errors
let userData = try ProfileError.catch {
let user = try database.loadUser(id)
let settings = try fileSystem.readUserSettings(user.settingsPath)
return UserProfile(user: user, settings: settings)
}
return userData
}
}
Read more about Typed Throws and Error Nesting →
When using Throwable
with the Catching
protocol, you get powerful error chain debugging:
do {
try await updateUserProfile()
} catch {
Logger().error("\(ErrorKit.errorChainDescription(for: error))")
// Output shows the complete error path:
// ProfileError
// └─ DatabaseError
// └─ FileError.notFound(path: "/Users/data.db")
// └─ userFriendlyMessage: "Could not find database file."
}
Read more about Error Chain Debugging →
Stop reinventing common error types in every project. ErrorKit provides standardized error types for common scenarios:
func fetchUserData() throws(DatabaseError) {
guard isConnected else {
throw .connectionFailed
}
// Fetching logic
}
Includes ready-to-use types like DatabaseError
, NetworkError
, FileError
, ValidationError
, PermissionError
, and more – all conforming to both Throwable
and Catching
with localized messages.
For quick one-off errors, use GenericError
:
func quickOperation() throws {
guard condition else {
throw GenericError(userFriendlyMessage: "The operation couldn't be completed due to invalid state.")
}
// Operation logic
}
Read more about Built-in Error Types →
Gathering diagnostic information from users has never been simpler:
Button("Report a Problem") {
showMailComposer = true
}
.mailComposer(
isPresented: $showMailComposer,
recipient: "[email protected]",
subject: "Bug Report",
messageBody: "Please describe what happened:",
attachments: [
try? ErrorKit.logAttachment(ofLast: .minutes(30))
]
)
With just a simple SwiftUI modifier, you can automatically include all log messages from Apple's unified logging system.
Read more about User Feedback and Logging →
ErrorKit's features are designed to complement each other while remaining independently useful:
-
Start with improved error definitions using
Throwable
for custom errors anduserFriendlyMessage(for:)
for system errors. -
Add type safety with Swift 6 typed throws, using the
Catching
protocol to solve nested error challenges. This pairs with error chain debugging to understand error flows through your app. -
Save time with ready-made tools: built-in error types for common scenarios and simple log collection for user feedback.
Here's a practical adoption strategy:
- Replace
Error
withThrowable
in your custom error types - Use
ErrorKit.userFriendlyMessage(for:)
when showing system errors - Adopt built-in error types where they fit your needs
- Implement typed throws with
Catching
for more robust error flows - Add error chain debugging to improve error visibility
- Integrate log collection with your feedback system
For complete documentation visit: ErrorKit Documentation
I created this library for my own Indie apps (download & rate them to show your appreciation):
App Icon | App Name & Description | Supported Platforms |
---|---|---|
![]() |
TranslateKit: App Localization
AI-powered app localization with unmatched accuracy. Fast & easy: AI & proofreading, 125+ languages, market insights. Budget-friendly, free to try. |
Mac |
![]() |
FreemiumKit: In-App Purchases for Indies
Simple In-App Purchases and Subscriptions: Automation, Paywalls, A/B Testing, Live Notifications, PPP, and more. |
iPhone, iPad, Mac, Vision |
![]() |
Pleydia Organizer: Movie & Series Renamer
Simple, fast, and smart media management for your Movie, TV Show and Anime collection. |
Mac |
![]() |
FreelanceKit: Project Time Tracking
Simple & affordable time tracking with a native experience for all devices. iCloud sync & CSV export included. |
iPhone, iPad, Mac, Vision |
![]() |
CrossCraft: Custom Crosswords
Create themed & personalized crosswords. Solve them yourself or share them to challenge others. |
iPhone, iPad, Mac, Vision |
![]() |
FocusBeats: Pomodoro + Music
Deep Focus with proven Pomodoro method & select Apple Music playlists & themes. Automatically pauses music during breaks. |
iPhone, iPad, Mac, Vision |
![]() |
Posters: Discover Movies at Home
Auto-updating & interactive posters for your home with trailers, showtimes, and links to streaming services. |
Vision |