Making Swift Error Messages Human-Friendly—Together
Swift error messages can be cryptic, but as a community, we can make them clearer. Help others (and your future self) by contributing better explanations.

Despite Swift’s elegant design, system error messages are often cryptic and unhelpful. Instead of just complaining, I created ErrorKit, a tool that maps these messages to human-friendly descriptions. But mapping Apple’s entire ecosystem is too big a task for one person—this needs to be a community effort.
In this post, I'll share the foundation I've built for enhanced error descriptions and invite you to join me in creating a comprehensive dictionary of user-friendly error messages for Swift developers.
The Problem with System Error Messages
Let's look at some real examples of unhelpful system error messages:
// File system error
"The file couldn't be opened because it doesn't exist."
// Better message: "The file 'report.pdf' could not be found. Please verify the file name and location."
// Core Data error
"The operation couldn't be completed. (Cocoa error 133000.)"
// Better message: "The database has a validation error. One or more required fields are empty or have invalid values."
These default messages have several problems:
- They're often too technical for end users
- They lack context about what was being attempted
- They rarely offer suggestions for how to resolve the issue
- They're sometimes just plain wrong or misleading
- They may expose implementation details that users shouldn't see
Apple has thousands of error codes across dozens of frameworks, and many of these have existed for decades. While they've improved newer APIs, many older frameworks still return messages designed for developers, not users.
The Solution: Community-Curated Error Mappings
ErrorKit provides a function called userFriendlyMessage(for:)
that maps system errors to more helpful messages:
do {
let data = try Data(contentsOf: url)
// Process data...
} catch {
// Instead of showing the default message
// showAlert(error.localizedDescription)
// Show an enhanced message
showAlert(ErrorKit.userFriendlyMessage(for: error))
}
Behind the scenes, this function analyzes the error and returns a better description based on a growing set of known error types:
// Example from ErrorKit's implementation
enum FoundationErrorMapper: ErrorMapper {
static func userFriendlyMessage(for error: Error) -> String? {
let nsError = error as NSError
// URL loading errors
if nsError.domain == NSURLErrorDomain {
switch nsError.code {
case NSURLErrorNotConnectedToInternet:
return String(localized: "You are not connected to the Internet. Please check your connection.")
case NSURLErrorTimedOut:
return String(localized: "The request timed out. Please try again later.")
// Many more cases...
}
}
// File system errors
if nsError.domain == NSCocoaErrorDomain {
switch nsError.code {
case NSFileNoSuchFileError:
return String(localized: "The file could not be found.")
// Many more cases...
}
}
// More domains and error codes...
return nil // Fall back to default handling
}
}
Current Coverage and Examples
ErrorKit includes mappings for common errors across key Apple frameworks:
Foundation
- Network:
NSURLErrorNotConnectedToInternet
→ "Your device isn't connected to the internet. Please check your connection and try again." - File System:
NSFileNoSuchFileError
→ "The file 'report.pdf' could not be found. Please verify the file name and location."
Core Data
- Validation:
NSValidationErrorMinimum
→ "The database failed validation. Please check your inputs and try again." - Store Management:
NSPersistentStoreCoordinatorError
→ "Database error. This might be due to a recent app update or file corruption."
MapKit
- Directions:
MKErrorDirectionsNotFound
→ "No directions found for the requested route." - Location:
MKErrorLocationUnknown
→ "Current location unavailable. Please check location permissions."
Why We Need a Community Response
In an ideal world, Apple would fix all its confusing error messages. And to be fair, they’ve improved things—newer frameworks like SwiftUI are much clearer. But decades of legacy APIs still return cryptic, technical messages that may never be touched again.
This is where our community can make a real impact. No single developer has seen every obscure error—but together, we’ve seen most of them. By sharing what we’ve already figured out and rewriting these messages in plain language, we can create a resource that saves everyone time and improves the experience for developers and users alike.
How You Can Contribute
If you've rewritten a system error message to make it more helpful, you’re already doing the work—now you can share it. Here are the 3 general steps:
- Spot a bad message
Note the error domain and code, the operation that triggered it, and any useful info from theuserInfo
dictionary. - Write a better version
Use plain language. Be specific. Offer a helpful next step when it makes sense. - Submit it on GitHub
Open a pull request or issue on the ErrorKit repo with your improved message, the original context, and any notes.
Even small contributions can help thousands of developers and improve the user experience for millions!
Beyond Apple Frameworks: Mapping Any Library's Errors
While Apple frameworks are the primary focus, ErrorKit's error mapping system works with any error type. The ErrorMapper
protocol allows developers to create custom mappings for third-party libraries:
// Example mapper for Alamofire networking errors
enum AlamofireErrorMapper: ErrorMapper {
static func userFriendlyMessage(for error: Error) -> String? {
switch error {
case let afError as Alamofire.AFError:
switch afError {
case .sessionTaskFailed(let underlying):
if let urlError = underlying as? URLError {
switch urlError.code {
case .notConnectedToInternet:
return String(localized: "Your device isn't connected to the internet. Please check your connection and try again.")
case .timedOut:
return String(localized: "The server took too long to respond. Please try again later.")
default:
return nil
}
}
return nil
case .responseValidationFailed(let reason):
if case .unacceptableStatusCode(let code) = reason {
return String(localized: "The server returned error \(code). Please check your request or try again later.")
}
return nil
default:
return nil
}
default:
return nil
}
}
}
// Register for immediate use
ErrorKit.registerMapper(AlamofireErrorMapper.self)
This extensibility opens up possibilities for:
- Adding custom mappings in your app for popular libraries like Alamofire
- Creating mapper packages for closed-source SDKs like Stripe, Admob, etc.
- Sharing error mappings within teams or organizations
Conclusion
Error messages significantly impact user experience yet often go overlooked in development. ErrorKit's userFriendlyMessage(for:)
function creates a framework for transforming this through community collaboration—one where developers pool their knowledge to make the entire Swift ecosystem more user-friendly.
If you've decoded cryptic error messages, your experience is valuable. By contributing to ErrorKit, you can fix these issues not just for yourself, but for every Swift developer who faces the same challenges. Check out ErrorKit and share your solutions to build this community resource:
Have you encountered cryptic error messages in Apple frameworks? Have you made them more helpful for yourself? Let me know on socials (links below)!
A simple & fast AI-based translator for String Catalogs & more.
Get it now and localize your app to over 100 languages in minutes!