macro_rules! error {
(class = $class:expr, data = $data:tt, $($arg:tt)*) => { ... };
(data = $data:tt, $($arg:tt)*) => { ... };
(class = $class:expr, $($arg:tt)*) => { ... };
($($arg:tt)*) => { ... };
}Expand description
Raise an R error from Rust with rust_error class layering.
Rides the tagged-condition transport that every #[miniextendr] function uses.
The raised condition has class c("rust_error", "simpleError", "error", "condition").
An optional class = "name" form prepends a custom class for programmatic catching:
c("name", "rust_error", "simpleError", "error", "condition").
§Structured data = ... payloads
An optional data = ... form (after class, before the message) attaches
named fields to the condition object, rlang-abort()-style. Handlers read
them as e$<name> instead of parsing the message string:
// Single field:
mx::error!(class = "range_error", data = ("value", value), "value {value} out of range");
// Multiple fields (bracketed list of pairs):
mx::error!(
class = "validation_error",
data = [("value", value), ("min", 0), ("max", 100)],
"value {value} out of range"
);
// Keyed builder sugar (bare-ident keys, stringified by the macro):
mx::error!(
class = "validation_error",
data = { value = value, min = 0, max = 100 },
"value {value} out of range"
);tryCatch(validate(150L), validation_error = function(e) c(e$value, e$min, e$max))
# [1] 150 0 100Argument order is fixed: class = ... (optional), then data = ...
(optional), then the format message.
Supported value types: scalars and Vecs of i32, f64, bool, and
String (plus &str / Vec<&str>, converted to owned); their NA-aware
Option / Vec<Option<_>> forms (→ R NA); the wide-integer ladder (i64
/ u32); and the RValue::debug escape hatch for
any T: Debug. The payload must be Send — it travels through panic_any
and may cross the worker→main thread boundary, so live SEXPs cannot ride
along; the R objects are materialised on the main thread at the unwind
boundary. For nested lists or complex/raw values build an
RValue directly.
§See also
crate::warning!/crate::message!/crate::condition!— the non-error sibling kinds (warning continues execution; message is muffled bysuppressMessages; condition is silent without a handler).std::panic!— escape hatch with the samerust_errorclass layering but no custom-class slot. Use for true bugs / impossible states; reach forerror!when callers might want to route by class.AsRError— wrapsResult<_, E: std::error::Error>for value-style propagation through Rust code; converts at the boundary.crate::error_value— module-level rationale for the tagged-SEXP transport and theerror_in_rdefault.
Name-collision note. Because pub mod error exists at the crate root,
use miniextendr_api::error imports the module rather than this macro.
Invoke via miniextendr_api::error!(...) (fully qualified) or via
mx::error!(...) after use miniextendr_api as mx;.
§Examples
use miniextendr_api as mx;
#[miniextendr]
fn fail() {
mx::error!("something went wrong: {}", 42);
}
// With a custom class for tryCatch:
#[miniextendr]
fn typed_fail(name: &str) {
mx::error!(class = "my_error", "missing field: {name}");
}tryCatch(fail(), rust_error = function(e) conditionMessage(e))
# [1] "something went wrong: 42"
tryCatch(typed_fail("x"), my_error = function(e) "caught!")
# [1] "caught!"