22.1 Introduction

Finding bug in code, is a process of confirming the many things that we believe are true — until we find one which is not true.

—Norm Matloff

Stretegies for finding and fixing errors

Google!: Whenever you see an error message, start by googling it. If you’re lucky, you’ll discover that it’s a common error with a known solution. When googling, improve your chances of a good match by removing any variable names or values that are specific to your problem.

We can automate this process with the errorist107 and searcher108 packages. See their websites for more details.

Make it repeatable: - To find the root cause of an error, you’re going to need to execute the code many times as you consider and reject hypotheses.

  • To make that iteration as quick as possible, it’s worth some upfront investment to make the problem both easy and fast to reproduce.

Figure out where it is: If you’re lucky, one of the tools in the following section will help you to quickly identify the line of code that’s causing the bug. Usually, however, you’ll have to think a bit more about the problem. It’s a great idea to adopt the scientific method. Generate hypotheses, design experiments to test them, and record your results. This may seem like a lot of work, but a systematic approach will end up saving you time.

Fix it and test it: Once you’ve found the bug, you need to figure out how to fix it and to check that the fix actually worked. Again, it’s very useful to have automated tests in place. Not only does this help to ensure that you’ve actually fixed the bug, it also helps to ensure you haven’t introduced any new bugs in the process. In the absence of automated tests, make sure to carefully record the correct output, and check against the inputs that previously failed.

Locating errors: Once you’ve made the error repeatable, the next step is to figure out where it comes from. The most important tool for this part of the process is traceback(), which shows you the sequence of calls (also known as the call stack, Section 7.5) that lead to the error.

  • Here’s a simple example: we can see that f() calls g() calls h() calls i(), which checks if its argument is numeric:

When we run f(“a”) code in RStudio we see:

Two options appear to the right of the error message: “Show Traceback” and “Rerun with Debug”. If you click “Show traceback” you see:

If you’re not using RStudio, you can use traceback() to get the same information (sans pretty formatting):

NB: You read the traceback() output from bottom to top: the initial call is f(), which calls g(), then h(), then i(), which triggers the error. If you’re calling code that you source()d into R, the traceback will also display the location of the function, in the form filename.r#linenumber. These are clickable in RStudio, and will take you to the corresponding line of code in the editor.