bevyengine/bevy · error

Can only derive VariantDefaults for enums

Error message

Can only derive VariantDefaults for enums

What it means

The `VariantDefaults` derive generates a `default_<variantname>()` constructor for every variant of an enum, using each field's `Default`. At variant_defaults.rs:10 the macro does `let Data::Enum(..) = &ast.data else { panic!(..) }`, so applying it to anything that is not an enum panics at compile time.

Source

Thrown at crates/bevy_ecs/macros/src/variant_defaults.rs:11

use bevy_macro_utils::fq_std::FQDefault;
use proc_macro::TokenStream;
use quote::{format_ident, quote, ToTokens};
use syn::{parse_macro_input, Data, DeriveInput};

pub(crate) fn derive_variant_defaults(input: TokenStream) -> TokenStream {
    let ast = parse_macro_input!(input as DeriveInput);
    let type_ident = &ast.ident;
    let (impl_generics, type_generics, where_clause) = &ast.generics.split_for_impl();
    let Data::Enum(data_enum) = &ast.data else {
        panic!("Can only derive VariantDefaults for enums");
    };

    let mut variant_defaults = Vec::new();
    for variant in &data_enum.variants {
        let variant_ident = &variant.ident;
        let variant_name_lower = variant_ident.to_string().to_lowercase();
        let variant_default_name = format_ident!("default_{}", variant_name_lower);
        match &variant.fields {
            syn::Fields::Named(fields_named) => {
                let fqdefault = FQDefault.into_token_stream();
                let fields = fields_named.named.iter().map(|f| &f.ident);
                variant_defaults.push(quote! {
                    #[allow(missing_docs)]
                    pub fn #variant_default_name() -> Self {
                        Self::#variant_ident {
                            #(#fields: #fqdefault::default(),)*
                        }
                    }

View on GitHub (pinned to 396ca72708)

Solutions

  1. Move `#[derive(VariantDefaults)]` onto an enum type
  2. Delete the derive from the struct/union if per-variant defaults make no sense there
  3. If you want struct-wide defaults, use `#[derive(Default)]` instead

Example fix

// before
#[derive(VariantDefaults)]
struct Config {
    difficulty: f32,
}

// after
#[derive(VariantDefaults, Default)]
enum Difficulty {
    #[default]
    Easy,
    Normal,
    Hard,
}
Defensive patterns

Strategy: validation

Validate before calling

cargo check --workspace # panics in the derive at compile time with file/line of the item

Prevention

When it happens

Trigger: `#[derive(VariantDefaults)]` on a `struct` or on a `union`. The let-else fails immediately after parsing the DeriveInput.

Common situations: Copy-pasting a derive list from an enum onto a struct during a refactor; IDE auto-import inserting every bevy derive; renaming an enum to a struct while keeping its derives.

Related errors


AI-assisted analysis of bevyengine/bevy@396ca72708 (2026-08-20). Data as JSON: /api/errors/f6b37423b58b168a. Report an issue: GitHub.