yewstack/yew · error · syn::Error
expected enum, found struct
Error message
expected enum, found struct
What it means
The #[derive(Routable)] macro (packages/yew-router-macro/src/routable_derive.rs:44) only accepts enums: a route model is a closed set of variants, each mapped to a URL pattern by an #[at("...")] attribute. Applying the derive to a struct is rejected at the struct token with 'expected enum, found struct'.
Source
Thrown at packages/yew-router-macro/src/routable_derive.rs:44
}
params
}
pub struct Routable {
ident: Ident,
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,View on GitHub (pinned to 0e4a05472f)
Solutions
- Convert the item into an enum where each variant is one route, with #[at("/path")] on every variant
- Use named fields on variants that capture route parameters (e.g. Post { id: u32 }) and unit variants for static routes
- If the struct must stay, remove the Routable derive and map the struct from an enum route model instead
Example fix
// before
#[derive(Routable, Clone)]
struct Routes {
home: (),
}
// after
#[derive(Routable, Clone)]
enum Routes {
#[at("/")]
Home,
} Defensive patterns
Strategy: validation
Validate before calling
// before deriving, confirm the item is an enum with one #[at] per variant
// #[derive(Routable, Clone)]
// enum Routes { #[at("/")] Home, #[at("/about")] { /* ... */ } About } Type guard
// compile-time shape check: fails to compile if Routes is not an enum
const _: fn(Routes) -> Routes = |r| match r { _ => r }; Prevention
- Reserve #[derive(Routable)] for enums only
- Model each route as one variant; parameters as named fields
- Put the derive on the item that represents your URL space, not on data payloads
When it happens
Trigger: Annotating a struct with #[derive(Routable)], e.g. #[derive(Routable, Clone)] struct Routes { home: () }. The derive input parser rejects Data::Struct before any route processing.
Common situations: Coming from routers where routes are a config struct or builder (actix, axum-style); holding route metadata in a struct and adding the derive as an afterthought; copy-pasting a derive list onto the wrong item.
Related errors
- expected enum, found union
- 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/99c647cb61d4c889.
Report an issue: GitHub.