{"record":{"id":"ee97888ed149a72a","repo":"linebender/druid","slug":"the-druid-attribute-has-been-replaced-with-separ","errorCode":null,"errorMessage":"The 'druid' attribute has been replaced with separate 'lens' and 'data' attributes.","messagePattern":"The 'druid' attribute has been replaced with separate 'lens' and 'data' attributes\\.","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"druid-derive/src/attr.rs","lineNumber":131,"sourceCode":"\n    pub fn iter(&self) -> impl Iterator<Item = &Field<Attrs>> {\n        self.fields.iter()\n    }\n}\n\nimpl Field<DataAttr> {\n    pub fn parse_ast(field: &syn::Field, index: usize) -> Result<Self, Error> {\n        let ident = match field.ident.as_ref() {\n            Some(ident) => FieldIdent::Named(ident.to_string().trim_start_matches(\"r#\").to_owned()),\n            None => FieldIdent::Unnamed(index),\n        };\n\n        let ty = field.ty.clone();\n\n        let mut data_attr = DataAttr::Empty;\n        for attr in field.attrs.iter() {\n            if attr.path.is_ident(BASE_DRUID_DEPRECATED_ATTR_PATH) {\n                panic!(\n                    \"The 'druid' attribute has been replaced with separate \\\n                    'lens' and 'data' attributes.\",\n                );\n            } else if attr.path.is_ident(BASE_DATA_ATTR_PATH) {\n                match attr.parse_meta()? {\n                    Meta::List(meta) => {\n                        assert!(\n                            meta.nested.len() <= 1,\n                            \"only single data attribute is allowed\"\n                        );\n                        if let Some(nested) = meta.nested.first() {\n                            match nested {\n                                NestedMeta::Meta(Meta::Path(path))\n                                    if path.is_ident(IGNORE_ATTR_PATH) =>\n                                {\n                                    data_attr = DataAttr::Ignore;\n                                }\n                                NestedMeta::Meta(Meta::NameValue(meta))","sourceCodeStart":113,"sourceCodeEnd":149,"githubUrl":"https://github.com/linebender/druid/blob/0f8b1195e4e073f9597f2865299c3d18f8e4005f/druid-derive/src/attr.rs#L113-L149","documentation":"The derive code for the `data` attribute parsing panics when it encounters the deprecated `#[druid(...)]` field attribute. The `druid` attribute namespace was split into separate `lens` and `data` attributes, and old usage is rejected outright rather than silently migrated.","triggerScenarios":"A struct field carries `#[druid(...)]` (matched by `BASE_DRUID_DEPRECATED_ATTR_PATH`) while the macro parses attributes to build `DataAttr`, inside `parse_ast`.","commonSituations":"Upgrading druid from an older version where `#[druid(...)]` was the documented attribute; copied example code from old tutorials or blog posts.","solutions":["Replace `#[druid(data = ...)]` with `#[data(...)]` on the field","Replace any `#[druid(lens = ...)]` usage with `#[lens(...)]`","Consult the druid-derive changelog for the attribute split migration"],"exampleFix":"// before\n#[derive(Data)]\nstruct S { #[druid(data = \"true\")] flag: bool }\n\n// after\n#[derive(Data)]\nstruct S { #[data(flag)] flag: bool }","handlingStrategy":"validation","validationCode":"// grep for the deprecated attribute before compiling:\n// grep -rn '#\\[druid(' src/","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Migrate all `#[druid(...)]` attributes to `#[data(...)]` / `#[lens(...)]` when upgrading druid","Run the compiler/CI early after version bumps to catch deprecated attributes","Update any internal snippets/templates that reference the old attribute"],"tags":["deprecated","derive-macro","attributes","migration"],"backgroundTag":"deprecated-api-usage","analyzedSha":"0f8b1195e4e073f9597f2865299c3d18f8e4005f","analyzedAt":"2026-09-10T14:27:34.582Z","contentChangedAt":"2026-09-10T14:27:34.582Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}