Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Throwing errors inside a root Task

Tags:

swift

I can't find anything in the docs how the following behavior is defined

// task-less context
Task.detached {
    try await myThrowingFunction()
    runWhenSuccessful()
}

The method returns on the throwing line and discards the error and runWhenSuccessful() will never be called. While it makes sense in some way, I at least expected it to trigger an assertion failure or something for the unhandled error.

What is the correct way to deal with this, since I can't handle errors in any parent task.

Am I expected to wrap everything in the closure in a do/catch every time?


1 Answers

For some reason Task is designed to silently fail when any errors are thrown inside the closure. Tasks do have a result property that you can read when the task has completed, but according to the documentation it will block the current thread where it's executed.

My preferred solution is to create a convenience initializer for Task that takes a failure closure.

This is what my custom initializer looks like, and how it would be used:

extension Task where Failure == Never, Success == Void {
    init(priority: TaskPriority? = nil, operation: @escaping () async throws -> Void, `catch`: @escaping (Error) -> Void) {
        self.init(priority: priority) {
            do {
                _ = try await operation()
            } catch {
                `catch`(error)
            }
        }
    }
}

Task {
    try await asyncTask()
} catch: { error in
    handle(error)
}
like image 97
EmilioPelaez Avatar answered Feb 26 '26 09:02

EmilioPelaez