ReasonedError
ReasonedError is a StructuredError subclass that adds a stable reason code.
It is used when an error needs not only a human-readable message and structured details, but also a machine-readable classifier.
Why it exists
Some errors must be interpreted programmatically.
A class name alone is often too coarse:
InvalidFunctionArgumentError
while the actual reason may vary:
empty
wrong_type
too_long
Relying on exception messages for this is fragile. ReasonedError introduces a
dedicated field (reason_code) for this purpose.
Basic usage
from mvx.common.errors import ReasonedError
error = ReasonedError(
message="Invalid function argument",
reason="empty",
details={"argument": "username"},
)
payload = error.to_log_payload()
The log payload includes the reason when present:
payload = {
"reason": "empty",
"kind": "ReasonedError",
"message": "Invalid function argument",
"details": {
"argument": "username",
},
}
Reason codes
Reason codes should be:
short;
stable;
machine-readable;
safe for logging.
Good examples:
empty
wrong_type
too_long
not_found
already_closed
Bad examples:
User name is empty
Something went wrong
Invalid value passed to the function
Using StrEnum
A recommended practice is to define reason codes using StrEnum.
This provides:
a closed set of allowed values;
IDE support and discoverability;
protection against typos;
compatibility with logging and serialization.
Example:
from enum import StrEnum
from mvx.common.errors import ReasonedError
class ValidationReason(StrEnum):
EMPTY = "empty"
WRONG_TYPE = "wrong_type"
TOO_LONG = "too_long"
error = ReasonedError(
message="Invalid function argument",
reason=ValidationReason.EMPTY,
details={"argument": "username"},
)
StrEnum values behave like strings:
reason = str(ValidationReason.EMPTY)
This makes them safe to use in logs, JSON, and other external representations.
Design rule
Use ReasonedError when the reason must be treated as data.
If the error only needs a message and structured context, use StructuredError
or a direct subclass of it.
API
- class mvx.common.errors.ReasonedError(*, message, details=None, cause=None, reason=None)
Bases:
StructuredErrorStructured error with an optional stable reason code.
Extends StructuredError by adding reason_code, which can be used as a machine-readable classifier for logging, metrics, and tests.
- Parameters:
message (
str) – Human-readable error message.details (
Optional[Mapping[str,Any]]) – Optional log-friendly diagnostic context.cause (
Optional[Exception]) – Optional underlying exception.reason (
Optional[str]) – Optional stable reason code.
- to_log_payload()
Extend base log payload with the reason code.
- Return type:
dict[str,Any]- Returns:
Log payload including “reason” when present.