risingwavelabs/risingwave · error

You can't use the macro on this type

Error message

You can't use the macro on this type

What it means

The #[serde_prefix_all] attribute macro only supports enums and structs. It fails at compile time when applied to a union or any other non-enum/non-struct item, because there is no defined way to prefix fields or variants of such a type. The error is emitted by try_prefix_all in the proc-macro crate when the derive input's Data falls into neither the Enum nor Struct arm.

Source

Thrown at src/common/proc_macro/src/serde_prefix_all.rs:134

        mode: mode.unwrap_or(Mode::Rename),
    })
}

pub(crate) fn try_prefix_all(
    args: AttributeArgs,
    mut input: DeriveInput,
) -> syn::Result<TokenStream> {
    let ParsedArgs {
        prefix,
        prefix_span,
        mode,
    } = parse_args(args)?;

    match &mut input.data {
        Data::Enum(item_enum) => handle_enum(item_enum, &prefix[..], mode)?,
        Data::Struct(item_struct) => handle_struct(item_struct, &prefix[..], mode)?,
        _ => {
            return Err(Error::new(
                prefix_span,
                "You can't use the macro on this type",
            ));
        }
    };

    Ok(input.to_token_stream().into())
}

fn create_attribute(prefix: &str, field_name: &str, mode: Mode) -> Attribute {
    let attr_prefix = format!("{prefix}{field_name}");
    match mode {
        Mode::Rename => parse_quote! { #[serde(rename = #attr_prefix)] },
        Mode::Alias => parse_quote! { #[serde(alias = #attr_prefix)] },
    }
}

fn take_skip_attr(attrs: &mut Vec<Attribute>) -> syn::Result<bool> {

View on GitHub (pinned to 6469eb736d)

Solutions

  1. Remove the #[serde_prefix_all] attribute from the union; the macro cannot run on unions.
  2. Convert the type to a struct (or enum) if prefixing semantics are actually needed.
  3. Handle prefixing manually with #[serde(rename = "...")] on each field instead.
  4. Move the attribute to a sibling struct/enum that wraps or serializes the union's payload.

Example fix

// before
#[serde_prefix_all("cfg_")]
union Packed {
    raw: u64,
    f: f64,
}

// after
#[derive(Serialize)]
#[serde_prefix_all("cfg_")]
struct PackedView {
    raw: u64,
}
Defensive patterns

Strategy: validation

Validate before calling

// Compile-time check before relying on the macro:
macro_rules! assert_is_struct_or_enum {
    ($t:ty) => {
        const _: () = {
            // Applying serde_prefix_all to a union fails to compile;
            // only attach it to structs/enums.
        };
    };
}
// Practical pre-check: confirm the item below the attribute is
// `struct` or `enum` — never `union`.

Prevention

When it happens

Trigger: Annotating a Rust `union` (or any item whose parsed DeriveInput data is not Data::Enum or Data::Struct) with #[serde_prefix_all("prefix")]. E.g. `#[serde_prefix_all("cfg_")] union Foo { a: u32, b: f32 }`.

Common situations: Developers converting a serde type to use the prefix macro accidentally apply it to a union used for FFI or low-level byte reinterpretation; copy-pasting the attribute above the wrong item; changing a struct into a union later and leaving the attribute in place.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11). Data as JSON: /api/errors/14e6eafb9eabd206. Report an issue: GitHub.