Home Comments Thread
New Thread

A Change in the Meaning of the Chunk Option `message = FALSE` / `warning = FALSE` | /en/2022/12/message-false/

giscus giscus 2022-12-19 23:22:22

A Change in the Meaning of the Chunk Option "message = FALSE" / "warning = FALSE"

With a new release of the evaluate package (v0.19) last week, the meanings of the chunk option message = FALSE and warning = FALSE in knitr have changed. Previously, they meant that messages and …

https://yihui.org/en/2022/12/message-false/

3 Comments

gadenbuie gadenbuie 2022-12-21 00:55:04

Hi! This is a nice improvement but I know that you obviously expected someone to be interested in redirecting warnings and messages to the console, so I’ll go ahead and be that person! 😇

I agree with you that the option values were unintuitive, but I frequently use the console output to diagnose or record problems in otherwise hard to reach places. For example, it’s extremely handy when rendering documents in a non-interactive environment like CI. It’d be great to have a way to opt into the old behavior.

😄 1
yihui yihui 2022-12-21 03:17:47

Feel free to be that person, and you will definitely get what you want in the next version of evaluate! :) I'll keep you posted. Thanks for the feedback!

yihui yihui 2022-12-22 03:59:20

With the dev versions of evaluate and knitr, you can go back to the old behavior with message = NA and warning = NA:

remotes::install_github(c('r-lib/evaluate', 'yihui/knitr'))
grimbough grimbough 2023-02-14 13:13:52

Bit late to the party, but are the message and warning options only expecting to be passed logicals? Prior to this change I passed character vectors of warnings that I expected to see in a code chunk, and used a custom knit_hooks$set(warning = "...") to suppress those expected outputs, but retain anything new that cropped up.

There's some crude examples at https://support.bioconductor.org/p/9141044/

With the new evaluate version I'm getting a variety of errors like below, presumably because keep_warning is expecting a logical and not anything else.

Error in keep_warning && getOption("warn") >= 0 : 
  invalid 'x' type in 'x && y'
yihui yihui 2023-02-14 15:27:21

Allowed values of message and warning options are documented at https://yihui.org/knitr/options/#text-output They can only take logical and numeric values. Character values worked by chance previously because they were treated as TRUE (yihui/knitr@5ff3888).

In your example, I suggest you rename options$warning to something like options$known_warning to avoid overloading the chunk option warning, and use the chunk option known_warning to pass the character vector of known warnings. Sorry about the hassle!

grimbough grimbough 2023-02-15 15:33:09

Thanks for the reply. I had a feeling we might have been abusing the warning option and getting away with it by chance. Adopting the strategy you suggested works great, and I've updated the example at https://support.bioconductor.org/p/9141044/#9149469 in case anyone else stumbles across it.

yihui yihui 2023-02-15 16:20:05

Great! Thank you very much!

slodge-work slodge-work 2023-10-04 12:48:08

I'm currently in the process of updating a large number of RMarkdown reports spread across a lot of repos to R4.3 - and I'm taking the opportunity to update their renv.lock files to modern tidyverse and rmarkdown/knitr as I go.

This area is causing me some challenges with our debug and monitoring logging at the moment.

We've traditionally setup our RMarkdown's so that they use a Log function which is a basic wrapper of message to output status information which helps us identify what's broken when an Rmd rendering job fails on our production servers - e.g. we might have blocks like:

---{r datafetch, message=FALSE, warning=FALSE}
Log("Fetching data for", param$code, "on", param$report_date)
data <- httr_fetch_for_data(some_url)
Log("Data fetched", nrow(data))
# ... data shaping, presentation added, etc
Log("Shaped data complete", nrow(some_shaped_data))
gt:gt(some_shaped_data) |> formatted()
---

On upgrading to the latest evaluate and knitr, this functionality now seems to be broken - our report knitting just outputs minimal debug info. We've found we can get some of the previous info back by call knitr::chunk_opts$set(message = NA, warning=NA) in our job processing code which is called before rmarkdown::render().

However, this doesn't seem to entirely work for us - especially because many of our Rmd's also have local overrides in place - e.g. many report authors have added knitr::chunk_opts$set(message=FALSE) lines or have used {r cars, message=FALSE} blocks locally in their R code in order to make their reports look beautiful during local debugging - and these local overrides replace our global NA setting.

If necessary, we can go through all these reports and replace all the blocks with e.g. {r cars, message=NA} but I'm wondering if this is really the right way to go. Is there any way we can instead set a global override here to ensure all message and warning information is passed to the console? As someone who often has to find out where problems are, I've always appreciated and used the console message output, and I would really appreciate having a global "please be verbose" setting that I can turn back on without having to go in and edit lots of individual Rmd blocks - plus trying to retrain lots of users who've got very used to adding message=FALSE.

PS I appreciate I'm also late to the discussion here too - renv has done a magnificent job of providing us with version stability this year, but it does mean we don't notice problems like this very quickly after package updates :)

yihui yihui 2023-10-04 15:19:48

Thanks for explaining the use case! That makes sense to me. knitr::opts_chunk$set(message = NA, warning = NA) before rmarkdown::render() is the right way to go. If users have overridden these options, you can further override them via an option hook, e.g.,

knitr::opts_hooks$set(message = function(options) {
    options$message = options$warning = NA
    options
})

Then you call rmarkdown::render(), and the option hook will make sure options message and warning will be NA.

---
title: Hello
---

```{r, message=FALSE}
message('Hello World!')
```

If you test the above example, you should see the message in the R console. Please let me know if that helps.

slodge slodge 2023-10-04 15:52:17

Thanks!

Testing that right now - and first few lines of rendering looks like it is working 👍

I think in our case, the messages really are there for debug and progress monitoring - I think we're the opposite of what you said:

When users set message = FALSE, the more likely intention is “I’m sure I don’t want to see any messages anywhere from this code chunk”, instead of “I don’t want to see messages in the output document but want to see them in the console”.

With that in mind... is there a way to enable this hook by default in RStudio Connect RMarkdown rendering too? I'm currently think we could just add that hook$set code to the RProfile.site file - I think that should work.

Thanks for the prompt response - and for saving me from having to edit lots of separate Rmd's in lots of repos :)

yihui yihui 2023-10-04 17:11:21

Yes, you can set the hook in .Rprofile or Rprofile.site.

slodge-work slodge-work 2023-10-04 19:33:55

Thanks - I think for our logs there we'll probably set those and also turn the progress bars off - so we really are the opposite of what I've seen others post!

Thanks for the prompt help and responses today - awesome.

yihui yihui 2023-10-04 19:59:49

I always welcome different voices and opinions. Your use case of logging and debugging was in my blind spot. I'm glad that we have found a solution anyway!

slodge-work slodge-work 2023-10-05 12:14:37

If it helps anyone else, this is what we've got in our Rprofile.site

setHook(packageEvent("knitr", "onLoad"),
        function(...) {
          message_default <- FALSE
          installed <- installed.packages()
          if ("evaluate" %in% rownames(installed)) {
            evaluate_installed <- installed["evaluate",]
            evaluate_version <- evaluate_installed[["Version"]]
            evaluate_version <- package_version(evaluate_version)
            if (evaluate_version == package_version("0.19")) {
              message("evaluate version 0.19 is broken - there is no way to get log messages out")
            }
            if (evaluate_version >= package_version("0.20")) {
              message_default <- NA
            }
          }
          knitr::opts_chunk$set(message = message_default, warning = message_default)
          knitr::opts_hooks$set(message = function(options) {
            options$message = message_default 
            options$warning = message_default
            options
          })
        })

That works for us - but might be NOISY for other people :)

yihui yihui 2023-10-05 14:30:01

Thanks for sharing the solution!

Just a few minor comments: 1) evaluate is guaranteed to be available when knitr is loaded, so you don't need to test if it's installed; 2) packageVersion() gives you a package version; 3) you can directly compare a version number with a string (the latter will be automatically coerced to a version number). With these in mind, here is how I'd write the code (feel free to adopt or discard):

setHook(
  packageEvent('knitr', 'onLoad'),
  function(...) {
    v = packageVersion('evaluate')
    if (v == '0.19') message(
      'evaluate v0.19 is broken - there is no way to get log messages out'
    )
    knitr::opts_hooks$set(message = function(options) {
      options$message = options$warning = if (v >= '0.20') NA else FALSE
      options
    })
  }
)
slodge slodge 2023-10-06 13:00:13

Would you consider a PR that set this as the default behaviour - e.g. via an ENV option - maybe something like KNITR_SEND_MESSAGES_TO_CONSOLE?

If this was available, I think people at our company we would set it "TRUE" for all our user and server machines by default. Further, other people, who enjoy the silence more, would be able to "turn logging on/off" very easily - e.g. Posit Connect users would be able to easily turn verbose messages on/off for individual reports using the env tab in the Connect UI.

yihui yihui 2023-10-09 15:31:11

If you prefer using env vars, you can use R_KNITR_OPTIONS, e.g.,

R_KNITR_OPTIONS="knitr.chunk.message=NA,knitr.chunk.warning=NA"

This has existed for years but never been undocumented. It's not as terse as what you suggested, but is a general solution when you want to change the default values of any chunk options.

slodge-work slodge-work 2023-10-09 16:54:14

I was thinking I want a stronger option than that - I want an option that reverts the package to the old console logging behaviour regardless of any message=FALSE existing in code - i.e. similar to the setHook code.

But if it's not something we want to add to the package then no worries (y)

yihui yihui 2023-10-09 17:42:01

Oh I see what you mean now. In theory, I could add an env var. It should be a fairly simple change in either knitr or evaluate. Let me think more for a moment.

yihui yihui 2023-10-10 16:14:22

Done via r-lib/evaluate@ee0fa82. You can set R_EVALUATE_BYPASS_MESSAGES=true to get what you want.

slodge-work slodge-work 2023-10-10 16:21:44

Thanks.

I do expect this will be very useful for Connect users who want to get some temporary verbose output 👍

yihui yihui 2023-11-07 15:13:02

FYI the new version of evaluate is on CRAN now: https://cran.r-project.org/package=evaluate

Sign in to join the discussion

Sign in with GitHub