Chapters

Hide chapters

Combine: Asynchronous Programming With Swift

Fourth Edition · iOS 16 · Swift 5.8 · Xcode 14

16. Error Handling
Written by Shai Mishali

Heads up... You’re accessing parts of this content for free, with some sections shown as scrambled text.

Heads up... You’re accessing parts of this content for free, with some sections shown as scrambled text.

Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.

Unlock now

You’ve learned a lot about how to write Combine code to emit values over time. One thing you might have noticed, though: Throughout most of the code you’ve written so far, you didn’t deal with errors at all, and mostly handled the “happy path.”

Unless you write error-free apps, this chapter is for you! :]

As you learned in Chapter 1, “Hello, Combine!,” a Combine publisher declares two generic constraints: Output, which defines the type of values the publisher emits, and Failure, which defines what kind of failure this publisher can finish with.

Up to this point, you’ve focused your efforts on the Output type of a publisher and failed to take a deep dive into the role of Failure in publishers. Well, don’t worry, this chapter will change that!

Publisher <Output, Failure> You are here!

Getting Started

Open the starter playground for this chapter in projects/Starter.playground. You’ll use this playground and its various pages to experiment with the many ways Combine lets you handle and manipulate errors.

You’re now ready to take a deep dive into errors in Combine, but first, take a moment to think about it. Errors are such a broad topic, where would you even start?

Well, how about starting with the absence of errors?

Never

A publisher whose Failure is of type Never indicates that the publisher can never fail.

Qof inmp sotejw qojd e yekwdesout axozq: Vispiwsaw <Ewn,Joheq> Ak dup yeyek ruig, hi gbon kah’f neccuz: 8 9 0 1 1 5

setFailureType

The first way to turn an infallible publisher into a fallible one is to use setFailureType. This is another operator only available for publishers with a failure type of Never.

assign(to:on:)

The assign operator you learned about in Chapter 2, “Publishers & Subscribers,” only works on publishers that cannot fail, same as setFailureType. If you think about it, it makes total sense. Sending an error to a provided key path results in either an unhandled error or undefined behavior.

assign(to:)

There is one tricky part about assign(to:on:) — It’ll strongly capture the object provided to the on argument.

ImjHibtigbapka yupp afbeqm(wu: xazpijqCozu, ad: ) gacg wmejo(om: ) &hesdmxajzaukj

assertNoFailure

The assertNoFailure operator is useful when you want to protect yourself during development and confirm a publisher can’t finish with a failure event. It doesn’t prevent a failure event from being emitted by the upstream. However, it will crash with a fatalError if it detects an error, which gives you a good incentive to fix it in development.

Dealing With Failure

Wow, so far you’ve learned a lot about how to deal with publishers that can’t fail at all… in an error-handling chapter! :] While a bit ironic, I hope you can now appreciate how critical it is to thoroughly understand the traits and guarantees of infallible publishers.

try* Operators

In Section II, “Operators,” you learned about most of Combine’s operators and how you can use them to manipulate the values and events your publishers emit. You also learned how to compose a logical chain of multiple operators to produce the output you want.

Mapping Errors

The differences between map and tryMap go beyond the fact that the latter allows throwing errors. While map carries over the existing failure type and only manipulates the publisher’s values, tryMap does not — it actually erases the error type to a plain Swift Error. This is true for all operators when compared to their try-prefixed counterparts.

Designing Your Fallible APIs

When constructing your own Combine-based code and APIs, you’ll often use APIs from other sources that return publishers that fail with various types. When creating your own APIs, you would usually want to provide your own errors around that API as well. It’s easier to experiment with this instead of just theorizing, so you’ll go ahead and dive into an example!

Catching And Retrying

You learned a ton about error handling for your Combine code, but we’ve saved the best for last with two final topics: catching errors and retrying failed publishers.

Key Points

  • Publishers with a Failure type of Never are guaranteed to not emit a failure completion event.
  • Many operators only work with infallible publishers. For example: sink(receiveValue:), setFailureType, assertNoFailure and assign(to:on:).
  • The try-prefixed operators let you throw errors from within them, while non-try operators do not.
  • Since Swift doesn’t support typed throws, calling try-prefixed operators erases the publisher’s Failure to a plain Swift Error.
  • Use mapError to map a publisher’s Failure type, and unify all failure types in your publisher to a single type.
  • When creating your own API based on other publishers with their own Failure types, wrap all possible errors into your own Error type to unify them and hide your API’s implementation details.
  • You can use the retry operator to resubscribe to a failed publisher for an additional number of times.
  • replaceError(with:) is useful when you want to provide a default fallback value for your publisher, in case of failure.
  • Finally, you may use catch to replace a failed publisher with a different fallback publisher.

Where to Go From Here?

Congratulations on getting to the end of this chapter. You’ve mastered basically everything there is to know about error handling in Combine.

Have a technical question? Want to report a bug? You can ask questions and report bugs to the book authors in our official book forum here.
© 2026 Kodeco Inc.

You’re accessing parts of this content for free, with some sections shown as scrambled text. Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.

Unlock now