Skip to main content

ContractError

Derive Macro ContractError 

Source
#[derive(ContractError)]
{
    // Attributes available to this derive:
    #[error_code]
    #[error_domain]
    #[canonical]
    #[contract_error]
}
Expand description

#[derive(ContractError)] — wire a typed Rust error enum into the PRD #1536 RFC 9457 envelope.

Per-variant attributes:

  • #[error_code("INSUFFICIENT_FUNDS")] (required)
  • #[error_domain("billing.v1")] (required, or set once on the enum)
  • #[canonical(FailedPrecondition)] (required — one of the 16 ProblemCategory variants)

Generates From<MyError> for Problem (server-side) and TryFrom<Problem> for MyError (client-side); unknown error_code/error_domain pairs round-trip back as the original Problem so callers can still handle them as generic envelopes.

Mark exactly one variant #[contract_error(fallback)] (unit, or a single named field receiving the original Problem) to additionally generate a total From<TransportError> for MyError, gated on the SDK having either the rest-client or the grpc-client feature. Both generated clients call that conversion on every failure, and they use it to reconstruct typed variants from an RFC 9457 envelope — the response body over HTTP, the x-toolkit-problem-bin trailer over gRPC — and to route un-reconstructable transport/protocol failures into the fallback variant.

Declare a ContractError enum as a contract method’s error type whenever the caller branches on a typed variant’s payload. CanonicalError cannot carry one: it has no field for error_code, error_domain or context["data"], so converting through it strips the domain identity in both directions, and for the categories whose context type has required fields (FailedPrecondition, ResourceExhausted, InvalidArgument, Aborted) it also loses or corrupts the category.

The fallback field may be Problem or Box<Problem>. Prefer the boxed form: a Problem is ~208 bytes and the fallback variant sets the size of the whole enum, hence of every Result<_, MyError> the contract returns, which trips clippy::result_large_err on each generated method.