diff --git a/spec/README.md b/spec/README.md
index c9d3642964..f35e7f4873 100644
--- a/spec/README.md
+++ b/spec/README.md
@@ -15,8 +15,7 @@
1. [Syntax Errors](errors.md#syntax-errors)
1. [Data Model Errors](errors.md#data-model-errors)
1. [Resolution Errors](errors.md#resolution-errors)
- 1. [Selection Errors](errors.md#selection-errors)
- 1. [Formatting Errors](errors.md#formatting-errors)
+ 1. [Message Function Errors](errors.md#message-function-errors)
1. [Registry](registry.md)
1. [`registry.dtd`](registry.dtd)
1. [Formatting](formatting.md)
diff --git a/spec/errors.md b/spec/errors.md
index f152edb77d..71ded38d1e 100644
--- a/spec/errors.md
+++ b/spec/errors.md
@@ -16,12 +16,13 @@ and MUST be emitted as soon as possible.
The other error categories are only emitted during formatting,
but it might be possible to detect them with validation tools.
-During selection, an _expression_ handler MUST only emit _Resolution Errors_ and _Selection Errors_.
-During formatting, an _expression_ handler MUST only emit _Resolution Errors_ and _Formatting Errors_.
+During selection and formatting,
+_expression_ handlers MUST only emit _Message Function Errors_.
-_Resolution Errors_ and _Formatting Errors_ in _expressions_ that are not used
-in _pattern selection_ or _formatting_ MAY be ignored,
-as they do not affect the output of the formatter.
+Implementations do not have to check for or emit _Resolution Errors_
+or _Message Function Errors_ in _expressions_ that are not otherwise used by the _message_,
+such as _placeholders_ in unselected _patterns_
+or _declarations_ that are never referenced during _formatting_.
In all cases, when encountering a runtime error,
a message formatter MUST provide some representation of the message.
@@ -34,7 +35,7 @@ SHOULD prioritise _Syntax Errors_ and _Data Model Errors_ over others.
When an error occurs within a _selector_,
the _selector_ MUST NOT match any _variant_ _key_ other than the catch-all `*`
-and a _Resolution Error_ or a _Selection Error_ MUST be emitted.
+and a _Resolution Error_ or a _Message Function Error_ MUST be emitted.
## Syntax Errors
@@ -241,82 +242,53 @@ or for private implementation use that is not supported by the current implement
> * {{The value is not one.}}
> ```
-### Invalid Expression
-
-An **_Invalid Expression_** error occurs when a _message_ includes an _expression_
-whose implementation-defined internal requirements produce an error during _function resolution_
-or when a _function_ returns a value (such as `null`) that the implementation does not support.
-
-An **_Operand Mismatch Error_** is an _Invalid Expression_ error that occurs when
-an _operand_ provided to a _function_ during _function resolution_ does not match one of the
-expected implementation-defined types for that function;
-or in which a literal _operand_ value does not have the required format
-and thus cannot be processed into one of the expected implementation-defined types
-for that specific _function_.
-
-> For example, the following _message_ produces an _Operand Mismatch Error_
-> (a type of _Invalid Expression_ error)
-> because the literal `|horse|` does not match the production `number-literal`,
-> which is a requirement of the function `:number` for its operand:
-> ```
-> .local $horse = {horse :number}
-> {{You have a {$horse}.}}
-> ```
-> The following _message_ might produce an _Invalid Expression_ error if the
-> the function `:function` threw an exception or otherwise emitted an error
-> rather than returning a valid value:
->```
-> {{This has an invalid expression {$var :function} because it has a bug in it.}}
->```
-
### Unsupported Statement
An **_Unsupported Statement_** error occurs when a message includes a _reserved statement_.
> For example, attempting to format this message
-> would always result in an _Unsupported Statement_ error:
+> would result in an _Unsupported Statement_ error:
>
> ```
> .some {|horse|}
> {{The message body}}
> ```
-## Selection Errors
+### Bad Selector
-**_Selection Errors_** occur when message selection fails.
+A **_Bad Selector_** error occurs when a message includes a _selector_
+with a resolved value which does not support selection.
-> For example, attempting to format either of the following messages
-> might result in a _Selection Error_ if done within a context that
-> uses a `:number` selector function which requires its input to be numeric:
->
-> ```
-> .match {|horse| :number}
-> 1 {{The value is one.}}
-> * {{The value is not one.}}
-> ```
+> For example, attempting to format this message
+> would result in a _Bad Selector_ error:
>
> ```
-> .local $sel = {|horse| :number}
-> .match {$sel}
-> 1 {{The value is one.}}
-> * {{The value is not one.}}
+> .local $day = {|2024-05-01| :date}
+> .match {$day}
+> * {{The due date is {$day}}}
> ```
-## Formatting Errors
+## Message Function Errors
+
+A **_Message Function Error_** is any error that occurs
+when calling a message function implementation
+or which depends on validation associated with a specific function.
-**_Formatting Errors_** occur during the formatting of a resolved value,
-for example when encountering a value with an unsupported type
-or an internally inconsistent set of options.
+Implementations SHOULD provide a way for _functions_ to emit
+(or cause to be emitted) any of the types of error defined in this section.
+Implementations MAY also provide implementation-defined _Message Function Error_ types.
> For example, attempting to format any of the following messages
-> might result in a _Formatting Error_ if done within a context that
+> might result in a _Message Function Error_ if done within a context that
>
-> 1. provides for the variable reference `$user` to resolve to
+> 1. Provides for the variable reference `$user` to resolve to
> an object `{ name: 'Kat', id: 1234 }`,
-> 2. provides for the variable reference `$field` to resolve to
+> 2. Provides for the variable reference `$field` to resolve to
> a string `'address'`, and
-> 3. uses a `:get` formatting function which requires its argument to be an object and
-> an option `field` to be provided with a string value,
+> 3. Uses a `:get` message function which requires its argument to be an object and
+> an option `field` to be provided with a string value.
+>
+> The exact type of _Message Function Error_ is determined by the message function implementation.
>
> ```
> Hello, {horse :get field=name}!
@@ -335,3 +307,64 @@ or an internally inconsistent set of options.
> Your {$field} is {$id :get field=$field}
> ```
+### Bad Operand
+
+A **_Bad Operand_** error is any error that occurs due to the content or format of the _operand_,
+such as when the _operand_ provided to a _function_ during _function resolution_ does not match one of the
+expected implementation-defined types for that function;
+or in which a literal _operand_ value does not have the required format
+and thus cannot be processed into one of the expected implementation-defined types
+for that specific _function_.
+
+> For example, the following _messages_ each produce a _Bad Operand_ error
+> because the literal `|horse|` does not match the `number-literal` production,
+> which is a requirement of the function `:number` for its operand:
+>
+> ```
+> .local $horse = {|horse| :number}
+> {{You have a {$horse}.}}
+> ```
+>
+> ```
+> .match {|horse| :number}
+> 1 {{The value is one.}}
+> * {{The value is not one.}}
+> ```
+
+### Bad Option
+
+A **_Bad Option_** error is an error that occurs when there is
+an implementation-defined error with an _option_ or its value.
+These might include:
+- A required _option_ is missing.
+- Mutually exclusive _options_ are supplied.
+- An _option_ value provided to a _function_ during _function resolution_
+ does not match one of the implementation-defined types or values for that _function_;
+ or in which the literal _option_ value does not have the required format
+ and thus cannot be processed into one of the expected
+ implementation-defined types for that specific _function_.
+
+> For example, the following _message_ might produce a _Bad Option_ error
+> because the literal `foo` does not match the production `digit-size-option`,
+> which is a requirement of the function `:number` for its `minimumFractionDigits` _option_:
+>
+> ```
+> The answer is {42 :number minimumFractionDigits=foo}.
+> ```
+
+### Bad Variant Key
+
+A **_Bad Variant Key_** error is an error that occurs when a _variant_ _key_
+does not match the expected implementation-defined format.
+
+> For example, the following _message_ produces a _Bad Variant Key_ error
+> because `horse` is not a recognized plural category and
+> does not match the `number-literal` production,
+> which is a requirement of the `:number` function:
+>
+> ```
+> .match {42 :number}
+> 1 {{The value is one.}}
+> horse {{The value is a horse.}}
+> * {{The value is not one.}}
+> ```
diff --git a/spec/formatting.md b/spec/formatting.md
index 48235d4c55..6027175d39 100644
--- a/spec/formatting.md
+++ b/spec/formatting.md
@@ -250,8 +250,8 @@ the following steps are taken:
argument type `T` and return type `U`
for implementations of functions
such that `U` can be coerced to `T`.
- Implementations of a _function_ SHOULD emit an
- _Invalid Expression_ error for _operands_ whose resolved value
+ Implementations of a _function_ SHOULD emit a
+ _Bad Operand_ error for _operands_ whose resolved value
or type is not supported.
> [!NOTE]
@@ -307,13 +307,13 @@ the following steps are taken:
resolve the value of the _expression_ as the result of that function call.
If the call fails or does not return a valid value,
- emit a _Invalid Expression_ error.
+ emit the appropriate _Message Function Error_ for the failure.
Implementations MAY provide a mechanism for the _function_ to provide
additional detail about internal failures.
Specifically, if the cause of the failure was that the datatype, value, or format of the
_operand_ did not match that expected by the _function_,
- the _function_ might cause an _Operand Mismatch Error_ to be emitted.
+ the _function_ might cause a _Bad Operand_ error to be emitted.
In all failure cases, use the _fallback value_ for the _expression_ as the resolved value.
@@ -519,7 +519,7 @@ First, resolve the values of each _selector_:
1. Else:
1. Let `nomatch` be a resolved value for which selection always fails.
1. Append `nomatch` as the last element of the list `res`.
- 1. Emit a _Selection Error_.
+ 1. Emit a _Bad Selector_ error.
The form of the resolved values is determined by each implementation,
along with the manner of determining their support for selection.
@@ -735,7 +735,7 @@ each _text_ and _placeholder_ part of the selected _pattern_ is resolved and for
Resolved values cannot always be formatted by a given implementation.
When such an error occurs during _formatting_,
-an implementation SHOULD emit a _Formatting Error_ and produce a
+an implementation SHOULD emit an appropriate _Message Function Error_ and produce a
_fallback value_ for the _placeholder_ that produced the error.
A formatting function MAY substitute a value to use instead of a _fallback value_.
diff --git a/spec/registry.md b/spec/registry.md
index 32668e5f16..dad7b4ed46 100644
--- a/spec/registry.md
+++ b/spec/registry.md
@@ -288,7 +288,7 @@ The function `:string` provides string selection and formatting.
The _operand_ of `:string` is either any implementation-defined type
that is a string or for which conversion to a string is supported,
or any _literal_ value.
-All other values produce an _Invalid Expression_ error.
+All other values produce a _Bad Operand_ error.
> For example, in Java, implementations of the `java.lang.CharSequence` interface
> (such as `java.lang.String` or `java.lang.StringBuilder`),
@@ -600,7 +600,7 @@ The _function_ `:integer` performs selection as described in [Number Selection](
The _operand_ of a number function is either an implementation-defined type or
a literal whose contents match the `number-literal` production in the [ABNF](/spec/message.abnf).
-All other values produce an _Invalid Expression_ error.
+All other values produce a _Bad Operand_ error.
> For example, in Java, any subclass of `java.lang.Number` plus the primitive
> types (`byte`, `short`, `int`, `long`, `float`, `double`, etc.)
@@ -675,7 +675,7 @@ numeric selectors perform as described below.
1. Else if `key` is one of the keywords `zero`, `one`, `two`, `few`, `many`, or `other`, then
1. If `key` and `keyword` consist of the same sequence of Unicode code points, then
1. Append `key` as the last element of the list `resultKeyword`.
- 1. Else, emit a _Selection Error_.
+ 1. Else, emit a _Bad Variant Key_ error.
1. Return a new list whose elements are the concatenation of the elements (in order) of `resultExact` followed by the elements (in order) of `resultKeyword`.
> [!NOTE]
@@ -776,7 +776,7 @@ If no options are specified, this function defaults to the following:
The _operand_ of the `:datetime` function is either
an implementation-defined date/time type
or a _date/time literal value_, as defined in [Date and Time Operand](#date-and-time-operands).
-All other _operand_ values produce an _Invalid Expression_ error.
+All other _operand_ values produce a _Bad Operand_ error.
#### Options
@@ -784,7 +784,7 @@ The `:datetime` function can use either the appropriate _style options_
or can use a collection of _field options_ (but not both) to control the formatted
output.
-If both are specified, an _Invalid Expression_ error MUST be emitted
+If both are specified, a _Bad Option_ error MUST be emitted
and a _fallback value_ used as the resolved value of the _expression_.
> [!NOTE]
@@ -901,7 +901,7 @@ If no options are specified, this function defaults to the following:
The _operand_ of the `:date` function is either
an implementation-defined date/time type
or a _date/time literal value_, as defined in [Date and Time Operand](#date-and-time-operands).
-All other _operand_ values produce an _Invalid Expression_ error.
+All other _operand_ values produce a _Bad Operand_ error.
#### Options
@@ -924,7 +924,7 @@ If no options are specified, this function defaults to the following:
The _operand_ of the `:time` function is either
an implementation-defined date/time type
or a _date/time literal value_, as defined in [Date and Time Operand](#date-and-time-operands).
-All other _operand_ values produce an _Invalid Expression_ error.
+All other _operand_ values produce a _Bad Operand_ error.
#### Options
@@ -941,7 +941,7 @@ The function `:time` has these _options_:
The _operand_ of a date/time function is either
an implementation-defined date/time type
or a _date/time literal value_, as defined below.
-All other _operand_ values produce an _Invalid Expression_ error.
+All other _operand_ values produce a _Bad Operand_ error.
A **_date/time literal value_** is a non-empty string consisting of an ISO 8601 date,
or an ISO 8601 datetime optionally followed by a timezone offset.
@@ -963,7 +963,7 @@ For more information, see [Working with Timezones](https://w3c.github.io/timezon
> The [ABNF](/spec/message.abnf) and [syntax](/spec/syntax.md) of MF2
> do not formally define date/time literals.
> This means that a _message_ can be syntactically valid but produce
-> an _Operand Mismatch Error_ at runtime.
+> a _Bad Operand_ error at runtime.
> [!NOTE]
> String values passed as variables in the _formatting context_'s