yewstack/yew · error · syn::Error
expected enum, found union
Error message
expected enum, found union
What it means
The #[derive(Routable)] macro (packages/yew-router-macro/src/routable_derive.rs:50) requires an enum because variants are matched one-to-one against URL patterns. Applying it to a union is rejected at the union token with 'expected enum, found union'.
Source
Thrown at packages/yew-router-macro/src/routable_derive.rs:50
ats: Vec<LitStr>,
variants: Punctuated<Variant, syn::token::Comma>,
not_found_route: Option<Ident>,
}
impl Parse for Routable {
fn parse(input: ParseStream) -> syn::Result<Self> {
let DeriveInput { ident, data, .. } = input.parse()?;
let data = match data {
Data::Enum(data) => data,
Data::Struct(s) => {
return Err(syn::Error::new(
s.struct_token.span(),
"expected enum, found struct",
));
}
Data::Union(u) => {
return Err(syn::Error::new(
u.union_token.span(),
"expected enum, found union",
));
}
};
let (not_found_route, ats) = parse_variants_attributes(&data.variants)?;
Ok(Self {
ident,
variants: data.variants,
ats,
not_found_route,
})
}
}
fn parse_variants_attributes(View on GitHub (pinned to 0e4a05472f)
Solutions
- Replace the union with an enum; each variant becomes a route with #[at("/path")]
- If the union is intentional for something else, remove the Routable derive from it entirely
Example fix
// before
#[derive(Routable, Clone)]
union Routes {
home: u32,
}
// after
#[derive(Routable, Clone)]
enum Routes {
#[at("/")]
Home,
} Defensive patterns
Strategy: validation
Validate before calling
// route models must be enums; verify the item kind before deriving
// enum Routes { #[at("/")] Home } Prevention
- Never apply Routable to unions or structs
- If a linter/rustfmt moves the derive, re-check which item it landed on
- Generate route enums from a single source of truth (macro or build script) to avoid hand-editing item kinds
When it happens
Trigger: Annotating a union item with #[derive(Routable)], e.g. union Routes { a: u32, b: f32 }. Data::Union is rejected before any variant attributes are read.
Common situations: Accidental paste of the derive onto a union declaration; machine-generated code that emits a union for a 'routes' type; experimenting with the derive on unusual item kinds.
Related errors
- expected enum, found struct
- only named fields are supported
- at attribute must be present on every variant
- this hook takes 2 arguments but 1 argument was supplied
- this hook takes 2 arguments but 1 argument was supplied
AI-assisted analysis of yewstack/yew@0e4a05472f (2026-08-22).
Data as JSON: /api/errors/431e1a03e18b0bb1.
Report an issue: GitHub.