stop
stop(..., call. = TRUE, domain = NULL) stop() is the primary way to signal an error in R. It halts execution immediately, prints an error message, and transfers control to the error handler. Every serious R package uses it internally, and you will reach for it whenever your code needs to fail fast on invalid input or impossible conditions.
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
... | objects | , | One or more objects coerced to character and pasted together. Can also be a single condition object. |
call. | logical | TRUE | If TRUE, the call that triggered stop() appears in the error message. Set to FALSE for cleaner output. |
domain | NULL or NA | NULL | Message translation domain. Use NA to suppress translation. |
Return value
stop() never returns. It halts execution and transfers control to the error handler.
Basic error signaling
The simplest use passes a character message:
validate_age <- function(age) {
if (age < 0) {
stop("Age cannot be negative")
}
if (age > 150) {
stop("Age value is implausible")
}
age
}
validate_age(-5)
# Error: Age cannot be negative
stop() accepts multiple arguments and pastes them without any separator, so include spaces explicitly. This is a common stumbling block: stop("value is", x) produces “value is42” instead of “value is 42”. The arguments are coerced to character individually and concatenated, which is convenient for building error messages from variables and string fragments in one call.
x <- NULL
stop("Object is", if (is.null(x)) " NULL" else " valid")
# Error: Object is NULL
The multi-argument paste behaviour also means you must include trailing spaces in each string fragment. stop("Error at index", i, "value", v) pastes everything without gaps. For cleaner error messages, use sprintf() or paste0() to build the message string beforehand, then pass a single argument to stop(). This avoids confusion and makes the error text predictable.
Controlling call display
The call. parameter determines whether the surrounding function call appears in the error output. Default is TRUE, which includes the full call:
tst_with_call <- function(x) {
stop("an error occurred", call. = TRUE)
}
tst_without_call <- function(x) {
stop("an error occurred", call. = FALSE)
}
tst_with_call(NULL)
# Error in tst_with_call(NULL) : an error occurred
tst_without_call(NULL)
# Error: an error occurred
In package code, call. = FALSE often produces less noisy messages. The choice depends on whether the caller context helps the user debug the problem.
Using condition objects
You can pass a condition object through ... instead of a character string. The condition must have class "error" or inherit from it:
my_error <- function(message) {
structure(
list(message = message),
class = c("my_error", "error", "condition")
)
}
tryCatch(
stop(my_error("custom condition object")),
error = function(e) {
cat("Caught: ", e$message, "\n")
}
)
# Caught: custom condition object
This pattern is the basis for custom error classes in R packages. By defining a condition class that inherits from "error", you can create domain-specific errors that tryCatch() dispatches to the appropriate handler based on class inheritance — class(e) %in% c("my_error", "error", "condition") means the handler matches on the custom class as well as the generic error class.
Using stop() with tryCatch()
stop() creates a condition of class error (specifically, an object inheriting from "simpleError"), which tryCatch() handles:
divide <- function(a, b) {
if (b == 0) stop("Division by zero")
a / b
}
result <- tryCatch(
divide(10, 0),
error = function(e) {
message("Error caught: ", e$message)
NA
}
)
# Error: Division by zero
# Error caught: Division by zero
# [1] NA
The error message prints before tryCatch() catches it, because R prints the message before invoking the default handler. To suppress the printed message, set options(show.error.messages" = FALSE) before the call.
Common mistakes
Expecting a return value. stop() never returns, code after stop() in the same block is never executed. If you wrap stop() in tryCatch(), the tryCatch() block returns whatever you specify in the error handler.
Forgetting separators in .... All arguments paste directly without spaces:
# WRONG
stop("value is", x) # no space before x
# RIGHT
stop("value is ", x) # explicit space
Using call. = TRUE in deep recursion. The call stack included in the error message grows with recursion depth, making the output harder to read.
stop() raises an error and halts execution. The error message can be caught with tryCatch(expr, error = function(e) ...). Pass call. = FALSE to omit the call stack from the error message, which is standard practice in package code for cleaner user-facing errors.
See also
tryCatch(), catch and handle errors with error handlerswithCallingHandlers(), establish local handlers with finer control- Error handling in R — patterns and best practices for careful error management