{"record":{"id":"e1c9e55e11121fe5","repo":"yewstack/yew","slug":"at-attribute-must-be-present-on-every-variant","errorCode":null,"errorMessage":"at attribute must be present on every variant","messagePattern":"at attribute must be present on every variant","errorType":"validation","errorClass":"syn::Error","httpStatus":null,"severity":"error","filePath":"packages/yew-router-macro/src/routable_derive.rs","lineNumber":93,"sourceCode":"\n    for variant in variants.iter() {\n        if let Fields::Unnamed(ref field) = variant.fields {\n            return Err(syn::Error::new(\n                field.span(),\n                \"only named fields are supported\",\n            ));\n        }\n\n        let attrs = &variant.attrs;\n        let at_attrs = attrs\n            .iter()\n            .filter(|attr| attr.path().is_ident(AT_ATTR_IDENT))\n            .collect::<Vec<_>>();\n\n        let attr = match at_attrs.len() {\n            1 => *at_attrs.first().unwrap(),\n            0 => {\n                return Err(syn::Error::new(\n                    variant.span(),\n                    format!(\"{AT_ATTR_IDENT} attribute must be present on every variant\"),\n                ));\n            }\n            _ => {\n                return Err(syn::Error::new_spanned(\n                    quote! { #(#at_attrs)* },\n                    format!(\"only one {AT_ATTR_IDENT} attribute must be present\"),\n                ));\n            }\n        };\n\n        let lit = attr.parse_args::<LitStr>()?;\n        let val = lit.value();\n\n        if val.find('#').is_some() {\n            return Err(syn::Error::new_spanned(\n                lit,","sourceCodeStart":75,"sourceCodeEnd":111,"githubUrl":"https://github.com/yewstack/yew/blob/0e4a05472fac4e5fce1befe60fa4a1e43a36b6a3/packages/yew-router-macro/src/routable_derive.rs#L75-L111","documentation":"Every variant of a #[derive(Routable)] enum must carry exactly one #[at(\"...\")] attribute so the derive can register it in the generated matchit router (packages/yew-router-macro/src/routable_derive.rs:93). A variant with zero #[at] attributes fails with 'at attribute must be present on every variant'. In this implementation the #[not_found] variant is not exempt — it also needs an #[at] path.","triggerScenarios":"Adding a new enum variant without an #[at] attribute; marking a fallback variant only with #[not_found] and omitting #[at]; renaming the attribute (e.g. #[route]) or using #[at] without a string literal argument.","commonSituations":"Extending a route enum during feature work and forgetting the attribute; migrating from an older yew-router where the not-found variant did not need a path; renaming 'at' while refactoring attributes.","solutions":["Add exactly one #[at(\"/path\")] to the offending variant — the error span points at the variant itself","For the fallback route keep #[not_found] but also add an #[at(\"/\")] or catch-all-style path as required by this derive","Do not duplicate #[at] on one variant; two or more triggers 'only one at attribute must be present'"],"exampleFix":"// before\n#[derive(Routable, Clone)]\nenum Routes {\n    #[at(\"/\")]\n    Home,\n    #[not_found]\n    NotFound,\n}\n\n// after\n#[derive(Routable, Clone)]\nenum Routes {\n    #[at(\"/\")]\n    Home,\n    #[at(\"/\")]\n    #[not_found]\n    NotFound,\n}","handlingStrategy":"validation","validationCode":"// every variant (including #[not_found]) needs exactly one #[at(\"...\")]\n// enum Routes {\n//     #[at(\"/\")] Home,\n//     #[at(\"/\")] #[not_found] NotFound,\n// }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Add the #[at] attribute in the same edit that adds the variant","Keep exactly one #[at] per variant — duplicates are also rejected","Remember the fallback variant is not exempt from #[at] in this derive"],"tags":["rust","derive-macro","yew-router","compile-time","routing"],"backgroundTag":"derive-macro-wrong-item-type","analyzedSha":"0e4a05472fac4e5fce1befe60fa4a1e43a36b6a3","analyzedAt":"2026-08-22T21:16:31.212Z","schemaVersion":2},"datasetVersion":"2026-08-23T01:17:44.959Z"}