Writing Robust Functions with stop() and warning()
Signal custom conditions from within your own functions.
Why Input Validation Matters
Defensive functions check their inputs and fail loudly with informative errors rather than silently producing wrong results. A function that catches bad input at the boundary is far easier to debug than one that propagates garbage through a pipeline.
# Without validation: wrong result, no error
bad_mean <- function(x) sum(x) / length(x)
bad_mean('hello') # no error, just NA
# With validation: clear error
good_mean <- function(x) {
if (!is.numeric(x)) stop('x must be numeric')
sum(x) / length(x)
}
tryCatch(good_mean('hello'), error = function(e) cat(e$message, '\n'))Informative Error Messages
Generic errors like stop('bad input') are frustrating to debug. Use paste0() or sprintf() inside stop() to include the actual value and expected type in the message. This saves time when tracing errors in pipelines.
check_numeric <- function(x, arg_name = 'x') {
if (!is.numeric(x)) {
stop(sprintf(
"'%s' must be numeric, but got class '%s'",
arg_name, class(x)
))
}
}
tryCatch(check_numeric('abc', 'score'),
error = function(e) cat(e$message, '\n'))All lessons in this course
- Errors, Warnings, and Messages in R
- tryCatch() for Error Recovery
- withCallingHandlers() and Restarts
- Writing Robust Functions with stop() and warning()