8.1 Introduction

The condition system provides a paired set of tools that allow the author of a function to indicate that something unusual is happening, and the user of that function to deal with it. The function author signals conditions with functions like stop() (for errors), warning() (for warnings), and message() (for messages), then the function user can handle them with functions like tryCatch() and withCallingHandlers(). Understanding the condition system is important because you’ll often need to play both roles: signalling conditions from the functions you create, and handle conditions signalled by the functions you call.

R offers a very powerful condition system based on ideas from Common Lisp. Like R’s approach to object-oriented programming, it is rather different to currently popular programming languages so it is easy to misunderstand, and there has been relatively little written about how to use it effectively. Historically, this has meant that few people (myself included) have taken full advantage of its power. The goal of this chapter is to remedy that situation. Here you will learn about the big ideas of R’s condition system, as well as learning a bunch of practical tools that will make your code stronger.

I found two resources particularly useful when writing this chapter. You may also want to read them if you want to learn more about the inspirations and motivations for the system:

I also found it helpful to work through the underlying C code that implements these ideas. If you’re interested in understanding how it all works, you might find my notes to be useful.

Quiz

Want to skip this chapter? Go for it, if you can answer the questions below. Find the answers at the end of the chapter in Section 8.7.

  1. What are the three most important types of condition?

  2. What function do you use to ignore errors in block of code?

  3. What’s the main difference between tryCatch() and withCallingHandlers()?

  4. Why might you want to create a custom error object?

Outline

  • Section 8.2 introduces the basic tools for signalling conditions, and discusses when it is appropriate to use each type.

  • Section 8.3 teaches you about the simplest tools for handling conditions: functions like try() and supressMessages() that swallow conditions and prevent them from getting to the top level.

  • Section 8.4 introduces the condition object, and the two fundamental tools of condition handling: tryCatch() for error conditions, and withCallingHandlers() for everything else.

  • Section 8.5 shows you how to extend the built-in condition objects to store useful data that condition handlers can use to make more informed decisions.

  • Section 8.6 closes out the chapter with a grab bag of practical applications based on the low-level tools found in earlier sections.

8.1.1 Prerequisites

As well as base R functions, this chapter uses condition signalling and handling functions from rlang.

library(rlang)