Passing argument names to cli function messages when called inside another function

I'm writing a package which has several functions with arguments that need to be of class Date. I have a function to check the argument input and run cli_abort if not, but the error message doesn't pick up the original argument name:

check_date <- function(date) {
    if (!lubridate::is.Date(date)) {
        cli::cli_abort(c(
             "{.var date} must have class {.cls Date}."))
    }
}

fun1 <- function(start_date, end_date) {
    check_date(start_date)
    check_date(end_date)
}

fun1(start_date = as.Date("2023-03-19"), end_date = "2023-03-30")
#> Error in `check_date()`:
#> ! `date` must have class <Date>.

Created on 2023-03-19 by the reprex package (v2.0.1)

Can I get cli_abort to show which argument caused the problem? i.e. have the last line of the output be

#> ! `end_date` must have class <Date>.

or whatever the original argument name was? Or is there an altogether different approach to this that may be preferable?

Thanks!

Yeah, you can use rlang::caller_env() and rlang::called_arg() to change the defaults for the call and the argument:

check_date <- function(date) {
  if (!lubridate::is.Date(date)) {
    cli::cli_abort(c(
      "{.var {rlang::caller_arg(date)}} must have class {.cls Date}.",
      "i" = "It was {.type {date}} instead."
    ), call = rlang::caller_env())
  }
}

fun1 <- function(start_date, end_date) {
    check_date(start_date)
    check_date(end_date)
}

fun1(start_date = as.Date("2023-03-19"), end_date = "2023-03-30")
#> Error in `fun1()`:
#> ! `end_date` must have class <Date>.
#> ℹ It was a string instead.
#> Run `rlang::last_trace()` to see where the error occurred.
1 Like

Thank you very much Gabor :grinning:

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.

If you have a query related to it or one of the replies, start a new topic and refer back with a link.