Skip to main content

ReplyError

Derive Macro ReplyError 

Source
#[derive(ReplyError)]
{
    // Attributes available to this derive:
    #[zlink]
}
Expand description

Derives ReplyError for enums, generating error definitions for Varlink service errors.

Requires the introspection feature to be enabled.

This macro generates implementations of the ReplyError trait, which provides a list of error variants that can be returned by a Varlink service method. It supports unit variants, variants with named fields, and single-field tuple variants (where the field type implements Type and has a Type::Object).

§Supported Attributes

The following attributes can be used to customize the behavior of this derive macro:

  • #[zlink(crate = "path")] - Specifies the crate path to use for zlink types. Defaults to ::zlink.

§Renaming

  • #[zlink(rename = "...")] on a field or variant sets its name in the IDL.
  • #[zlink(rename_all = "...")] on the enum applies to error names, and on a variant to that variant’s fields. An explicit rename on an item overrides it. Error names in the IDL are unqualified; the interface comes from #[zlink(interface)].

Valid rename_all values are lowercase, UPPERCASE, PascalCase, camelCase, snake_case, SCREAMING_SNAKE_CASE, kebab-case and SCREAMING-KEBAB-CASE. They mean the same as they do in serde.

These attributes do not affect serialization on their own. ReplyError reads the same #[zlink(rename)] and #[zlink(rename_all)] attributes, so deriving both on the same enum (the usual pairing) keeps the wire format and the IDL in sync automatically. Any other type that separately derives serde traits still needs the same renaming stated to serde, or the IDL will not describe what is actually sent:

use zlink::{ReplyError, introspect};

// `UPPERCASE`, not `SCREAMING_SNAKE_CASE`: an error name has no place for underscores
// (`[A-Z][A-Za-z0-9]*`), so the screaming-snake form would not be expressible in Varlink.
#[derive(ReplyError, introspect::ReplyError)]
#[zlink(interface = "org.example.Test", rename_all = "UPPERCASE")]
enum ServiceError {
    NotFound,
}

§Example

use zlink::introspect::ReplyError;

#[derive(ReplyError)]
enum ServiceError {
    // Unit variant - no parameters
    NotFound,

    // Named field variant - multiple parameters
    InvalidQuery {
        message: String,
        line: u32,
    },

    // Single tuple variant - uses fields from the wrapped type
    ValidationFailed(ValidationDetails),
}

// Example struct for tuple variant
#[derive(zlink::introspect::Type)]
struct ValidationDetails {
    field_name: String,
    expected: String,
}

// Access the generated error variants
assert_eq!(ServiceError::VARIANTS.len(), 3);
assert_eq!(ServiceError::VARIANTS[0].name(), "NotFound");
assert!(ServiceError::VARIANTS[0].has_no_fields());

assert_eq!(ServiceError::VARIANTS[1].name(), "InvalidQuery");
assert!(!ServiceError::VARIANTS[1].has_no_fields());

#[zlink(skip)] and #[zlink(flatten)] are not supported on error fields; they only apply to Type/CustomType, where they mirror a #[serde(..)] attribute.