Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

traceback for rendering R Markdown non-interactively no longer works #1792

Open
kelly-sovacool opened this issue Oct 31, 2024 · 0 comments
Open

Comments

@kelly-sovacool
Copy link

It used to be possible to get an informative traceback when rendering R Markdown non-interactively, where the traceback would only show function calls for code within the R Markdown notebook, as long as the notebook contained this code from the Debugging chapter:

options(rlang_trace_top_env = rlang::current_env())
options(error = function() {
    sink()
    print(rlang::trace_back(bottom = sys.frame(-1)), simplify = "none")
})

However, this behavior seems to have gone away with newer versions of R, knitr, rmarkdown, and rlang, and instead the traceback contains numerous knitr & rmarkdown function calls but nothing from the R Markdown source file itself.

example

Here's a simple notebook.Rmd that uses the above code and throws an error:

---
title: "example notebook"
output:
    html_document
params:
    to_error: true
---

```{r setup}
options(rlang_trace_top_env = rlang::current_env())
options(error = function() {
    sink()
    print(rlang::trace_back(bottom = sys.frame(-1)), simplify = "none")
})
knitr::opts_chunk$set(message = FALSE)
```

```{r error}
throw_error <- function(to_error) {
    func(to_error)
}
func <- function(to_error) {
    if (to_error) stop('ERROR')
}
message(paste("to_error:", params$to_error, "(", class(params$to_error), ")"))
throw_error(params$to_error)
```

Rendered from a terminal with:

R -e "rmarkdown::render('notebook.Rmd')"

where the global error option is NULL:

getOption('error')

NULL

older versions

With older versions:

  • R: 4.1.0
  • rmarkdown: 2.9
  • knitr: 1.33
  • rlang: 0.4.11

The output is helpful, only showing code from the R Markdown file in the traceback:

processing file: notebook.Rmd
  |..................                                                    |  25%
  ordinary text without R code

  |...................................                                   |  50%
label: setup
  |....................................................                  |  75%
  ordinary text without R code

  |......................................................................| 100%
label: error
to_error: TRUE ( logical )
Quitting from lines 19-27 (notebook.Rmd) 
Error in func(to_error) : ERROR
Calls: <Anonymous> ... withCallingHandlers -> withVisible -> eval -> eval -> throw_error -> func
    █
 1. └─global::throw_error(params$to_error)
 2.   └─global::func(to_error)
 3.     └─base::stop("ERROR")

Warning message:
In sink() : no sink to remove

newer versions

But with newer versions:

  • R: 4.4.1
  • rmarkdown: 2.28
  • knitr: 1.48
  • rlang: 1.1.4

The output is extremely verbose and includes rmarkdown & knitr calls in the stack, but crucially doesn't include underlying code from the R Markdown file.

processing file: notebook.Rmd
  |..............................................................| 100% [error]Error in `func()`:
! ERROR
Backtrace:
  1. rmarkdown::render("notebook.Rmd")
  2. knitr::knit(knit_input, knit_output, envir = envir, quiet = quiet)
  3. knitr:::process_file(text, output)
  6. knitr:::process_group(group)
  7. knitr:::call_block(x)
     ...
 14. base::withRestarts(...)
 15. base (local) withRestartList(expr, restarts)
 16. base (local) withOneRestart(withRestartList(expr, restarts[-nr]), restarts[[nr]])
 17. base (local) docall(restart$handler, restartArgs)
 19. evaluate (local) fun(base::quote(`<smplErrr>`))
     ▆
  1. ├─rmarkdown::render("notebook.Rmd")
  2. │ └─knitr::knit(knit_input, knit_output, envir = envir, quiet = quiet)
  3. │   └─knitr:::process_file(text, output)
  4. │     ├─xfun:::handle_error(...)
  5. │     ├─base::withCallingHandlers(...)
  6. │     └─knitr:::process_group(group)
  7. │       └─knitr:::call_block(x)
  8. │         └─knitr:::block_exec(params)
  9. │           └─knitr:::eng_r(options)
 10. │             ├─knitr:::in_input_dir(...)
 11. │             │ └─knitr:::in_dir(input_dir(), expr)
 12. │             └─knitr (local) evaluate(...)
 13. │               └─evaluate::evaluate(...)
 14. │                 └─base::withRestarts(...)
 15. │                   └─base (local) withRestartList(expr, restarts)
 16. │                     └─base (local) withOneRestart(withRestartList(expr, restarts[-nr]), restarts[[nr]])
 17. │                       └─base (local) docall(restart$handler, restartArgs)
 18. │                         ├─base::do.call("fun", lapply(args, enquote))
 19. │                         └─evaluate (local) fun(base::quote(`<smplErrr>`))
 20. │                           └─base::signalCondition(cnd)
 21. └─knitr (local) `<fn>`(`<smplErrr>`)
 22.   └─rlang::entrace(e)
 23.     └─rlang::cnd_signal(entraced)
 24.       └─rlang:::signal_abort(cnd)
 25.         └─base::stop(fallback)

Quitting from lines 19-27 [error] (notebook.Rmd)

Did something regress in one or some of these newer package versions? Or am I overlooking something about the R environment? How can I get a traceback showing only code from the R Markdown file, but using these newer versions of R, rmarkdown, knitr, and rlang?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant