{"record":{"id":"5c17c9ee0bbf407f","repo":"dbt-labs/dbt-core","slug":"protoenumserde-can-only-be-derived-for-enums","errorCode":null,"errorMessage":"ProtoEnumSerde can only be derived for enums","messagePattern":"ProtoEnumSerde can only be derived for enums","errorType":"validation","errorClass":"syn::Error","httpStatus":null,"severity":"error","filePath":"crates/proto-rust-macros/src/lib.rs","lineNumber":279,"sourceCode":"fn vec_path_for(ty: &Type) -> proc_macro2::TokenStream {\n    // Preserve the original vector path (Vec or ::prost::alloc::vec::Vec)\n    if let Type::Path(tp) = ty {\n        let segments = tp.path.segments.clone();\n        if let Some(last) = segments.last()\n            && last.ident == \"Vec\"\n        {\n            let path = &tp.path;\n            return quote! { #path };\n        }\n    }\n    quote! { ::prost::alloc::vec::Vec }\n}\n\nfn impl_proto_enum_serde(input: &DeriveInput) -> syn::Result<proc_macro2::TokenStream> {\n    match input.data {\n        Data::Enum(_) => {}\n        _ => {\n            return Err(syn::Error::new(\n                input.span(),\n                \"ProtoEnumSerde can only be derived for enums\",\n            ));\n        }\n    }\n\n    if !has_repr_i32(input) {\n        // Not an i32-backed enum; skip deriving anything per request.\n        return Ok(quote! {});\n    }\n\n    let enum_ident = &input.ident;\n\n    let ser_impl = quote! {\n        impl ::serde::Serialize for #enum_ident {\n            fn serialize<S>(&self, serializer: S) -> ::core::result::Result<S::Ok, S::Error>\n            where\n                S: ::serde::Serializer,","sourceCodeStart":261,"sourceCodeEnd":297,"githubUrl":"https://github.com/dbt-labs/dbt-core/blob/0267ce9170576975b76b64ce856b2e5848e96617/crates/proto-rust-macros/src/lib.rs#L261-L297","documentation":"The ProtoEnumSerde derive generates serde Serialize/Deserialize impls that round-trip a prost i32-backed enum through its proto string name. It only applies to Rust enums, so the macro rejects any input that is a struct or union with this compile-time error.","triggerScenarios":"Annotating `#[derive(ProtoEnumSerde)]` on a struct or union instead of an enum; accidentally placing the derive on the wrong item after a refactor that converted an enum to a struct.","commonSituations":"Copy-pasting derive lists between type declarations; mass renames/refactors where an enum became a struct with associated constants; IDE auto-import attaching the derive to the wrong block.","solutions":["Move `#[derive(ProtoEnumSerde)]` onto the enum declaration; ensure the enum is `#[repr(i32)]` (otherwise the derive silently emits nothing).","If the item really is a struct, remove the ProtoEnumSerde derive and derive serde's `Serialize`/`Deserialize` directly (e.g. with `#[serde(rename_all = ...)]`) instead.","For prost-generated enums, rely on the generated `as_str_name()`/`from_str_name()` and derive ProtoEnumSerde only on the wrapping enum."],"exampleFix":"// before\n#[derive(ProtoEnumSerde)]\npub struct Kind;\n\n// after\n#[derive(ProtoEnumSerde)]\n#[repr(i32)]\npub enum Kind {\n    Unspecified = 0,\n    Active = 1,\n}","handlingStrategy":"type-guard","validationCode":"// only enums qualify; verify before deriving\n// enum Kind { ... } with #[repr(i32)] for the serde impls to be emitted","typeGuard":"macro_rules! assert_enum {\n    (enum $name:ident { $($t:tt)* }) => {};\n    ($other:tt) => { compile_error!(\"ProtoEnumSerde can only be derived for enums\"); };\n}","tryCatchPattern":null,"preventionTips":["Attach ProtoEnumSerde only to `#[repr(i32)]` enum declarations","Keep derive lists adjacent to the item they belong to","Remember: enums without #[repr(i32)] silently get no impls"],"tags":["proc-macro","derive-macro","serde","rust","protobuf"],"backgroundTag":"unsupported-operation","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"}