Skip to main content

Debugging in R

R
group meeting
browser(), debugonce(), traceback() and recover(), with examples in plain scripts and in Shiny apps.
Published

July 10, 2025

I prepared this for an R session at our group meeting at the MRC Biostatistics Unit. It was first published on the group’s website.

Introduction

Debugging is essential in programming for identifying and resolving errors effectively. Good debugging skills enhance productivity and ensure code reliability.

Topics Covered:

  • browser()
  • debugonce()
  • traceback()
  • recover()
  • Debugging Shiny applications

The browser() Function

Purpose: Pauses execution, allowing interactive inspection.

Example:

my_function <- function(x) {
    y <- x + 10
    browser()
    z <- y / 2
    return(z)
}

my_function(5)

How to use:

  • Inspect variables directly.
  • Step through code (n for next, c to continue).

The debugonce() Function

Purpose: Debugs a function exactly once.

Example:

add_numbers <- function(a, b) {
    sum <- a + b
    return(sum)
}

debugonce(add_numbers)

add_numbers(3, "two")

How to use:

  • Automatically enters debug mode at next call.
  • Useful for inspecting unexpected errors inside functions.

The traceback() Function

Purpose: Identifies the call sequence leading to an error.

Example:

func_a <- function() { func_b() }
func_b <- function() { stop("An error occurred!") }

func_a()
traceback()

How to use:

  • Quickly identifies problematic calls.
  • Ideal for debugging nested functions.

The recover() Function

Purpose: Interactive debugging at the moment an error occurs.

Set this first:

options(error = recover)

f1 <- function(x) { f2(x) }
f2 <- function(x) { f3(x) }
f3 <- function(x) { stop("Unexpected error!") }

f1(10)

How to use:

  • Provides menu to enter error environments.
  • Inspect variables interactively.

Debugging Shiny Applications

Debugging Shiny can be challenging. Key approaches include:

  • Use browser() in reactive contexts:
library(shiny)

ui <- fluidPage(
    numericInput("num", "Number:", 10),
    textOutput("result")
)

server <- function(input, output) {
    output$result <- renderText({
        browser()
        paste("Double:", input$num * 2)
    })
}

shinyApp(ui, server)
  • Monitor logs and console outputs.

Summary: Key Takeaways

  • browser() - Interactive inspection.
  • debugonce() - Single-use debugging.
  • traceback() - Error call sequence.
  • recover() - Interactive error handling.
  • Shiny apps - Combine browser(), logging, and output checks.

Effective debugging greatly enhances coding efficiency and reliability.


References