abort() and error_cnd() create errors of class "rlang_error". The differences with base errors are:
• Implementing conditionMessage() methods for subclasses of "rlang_error" is undefined behaviour. Instead, implement the cnd_header() method (and possibly cnd_body() and cnd_footer()). These methods return character vectors which are assembled by rlang when needed: when conditionMessage.rlang_error() is called (e.g. via try()), when the error is displayed through print() or format(), and of course when the error is displayed to the user by abort().
• cnd_header(), cnd_body(), and cnd_footer() methods can be overridden by storing closures in the header, body, and footer fields of the condition. This is useful to lazily generate messages based on state captured in the closure environment.
• The use_cli_format condition field instructs whether to use cli (or rlang's fallback method if cli is not installed) to format the error message at print time.
In this case, the message field may be a character vector of header and bullets. These are formatted at the last moment to take the context into account (starting position on the screen and indentation).
See local_use_cli() for automatically setting this field in errors thrown with abort() within your package.