{"record":{"id":"e403a8651013e619","repo":"dbt-labs/dbt-core","slug":"protonew-can-only-be-derived-for-structs","errorCode":null,"errorMessage":"ProtoNew can only be derived for structs","messagePattern":"ProtoNew can only be derived for structs","errorType":"validation","errorClass":"syn::Error","httpStatus":null,"severity":"error","filePath":"crates/proto-rust-macros/src/lib.rs","lineNumber":53,"sourceCode":"        Err(err) => err.to_compile_error().into(),\n    }\n}\n\nfn impl_proto_new(input: &DeriveInput) -> syn::Result<proc_macro2::TokenStream> {\n    let struct_ident = &input.ident;\n\n    let fields = match &input.data {\n        Data::Struct(s) => match &s.fields {\n            Fields::Named(named) => &named.named,\n            _ => {\n                return Err(syn::Error::new(\n                    s.fields.span(),\n                    \"ProtoNew only supports structs with named fields\",\n                ));\n            }\n        },\n        _ => {\n            return Err(syn::Error::new(\n                input.span(),\n                \"ProtoNew can only be derived for structs\",\n            ));\n        }\n    };\n\n    // Build parameter list and field initializers\n    let mut params = Vec::new();\n    let mut inits = Vec::new();\n    let mut arg_docs: Vec<String> = Vec::new();\n\n    for field in fields {\n        let field_ident = field\n            .ident\n            .clone()\n            .ok_or_else(|| syn::Error::new(field.span(), \"Unnamed field not supported\"))?;\n\n        let is_enum = find_prost_enumeration_attr(&field.attrs)?;","sourceCodeStart":35,"sourceCodeEnd":71,"githubUrl":"https://github.com/dbt-labs/dbt-core/blob/0267ce9170576975b76b64ce856b2e5848e96617/crates/proto-rust-macros/src/lib.rs#L35-L71","documentation":"The ProtoNew derive macro can only be applied to struct items (Data::Struct). Applying it to an enum or union makes impl_proto_new return a syn::Error on the input's span with the message 'ProtoNew can only be derived for structs', failing compilation. This guard exists because the generated constructor logic is struct-specific.","triggerScenarios":"Adding `#[derive(ProtoNew)]` to an `enum` or `union` definition instead of a `struct`.","commonSituations":"Bulk-adding the derive to a module containing enums; applying derive helper patterns intended for structs to enum types; IDE auto-import applying the wrong derive attribute.","solutions":["Remove the ProtoNew derive from the enum/union","Restructure the type as a struct if a proto-style constructor is needed","Implement a separate derive macro if enums need equivalent functionality"],"exampleFix":"// before\n#[derive(ProtoNew)]\nenum NodeKind { Leaf, Branch }\n// after (derive removed; construct via normal enum variants)\nenum NodeKind { Leaf, Branch }","handlingStrategy":"validation","validationCode":"// Compile-time: ensure the item is a struct before deriving\n// enum Foo { A }  + #[derive(ProtoNew)] -> compile error pointing at the enum","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never place #[derive(ProtoNew)] on enums or unions","Audit bulk-added derive attributes after refactors","Keep enum serialization logic in a dedicated macro/impl instead of reusing ProtoNew"],"tags":["derive-macro","protobuf","compile-time","proc-macro"],"backgroundTag":"unsupported-derive-target","analyzedSha":"0267ce9170576975b76b64ce856b2e5848e96617","analyzedAt":"2026-09-07T21:53:39.732Z","contentChangedAt":"2026-09-07T21:53:39.732Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}