dbt-labs/dbt-core · error · syn::Error

ProtoNew only supports structs with named fields

Error message

ProtoNew only supports structs with named fields

What it means

The ProtoNew derive macro (impl_proto_new, invoked via derive_proto_new) only supports structs whose fields are all named (Fields::Named). Applying #[derive(ProtoNew)] to a tuple struct or unit struct makes the macro return a syn::Error at the fields' span, producing a compile-time error. Named fields are required because the macro generates a constructor keyed by field name.

Source

Thrown at crates/proto-rust-macros/src/lib.rs:46

/// and the initializer converts the enum value(s) back to i32 as needed.
#[proc_macro_derive(ProtoNew, attributes(prost))]
pub fn derive_proto_new(input: TokenStream) -> TokenStream {
    let input = parse_macro_input!(input as DeriveInput);

    match impl_proto_new(&input) {
        Ok(ts) => ts.into(),
        Err(err) => err.to_compile_error().into(),
    }
}

fn impl_proto_new(input: &DeriveInput) -> syn::Result<proc_macro2::TokenStream> {
    let struct_ident = &input.ident;

    let fields = match &input.data {
        Data::Struct(s) => match &s.fields {
            Fields::Named(named) => &named.named,
            _ => {
                return Err(syn::Error::new(
                    s.fields.span(),
                    "ProtoNew only supports structs with named fields",
                ));
            }
        },
        _ => {
            return Err(syn::Error::new(
                input.span(),
                "ProtoNew can only be derived for structs",
            ));
        }
    };

    // Build parameter list and field initializers
    let mut params = Vec::new();
    let mut inits = Vec::new();
    let mut arg_docs: Vec<String> = Vec::new();

View on GitHub (pinned to 0267ce9170)

Solutions

  1. Convert the struct to use named fields
  2. Remove the ProtoNew derive from the tuple/unit struct and construct it directly
  3. If ProtoNew should support tuple structs, extend the macro to handle Fields::Unnamed

Example fix

// before
#[derive(ProtoNew)]
struct Column(u32, String);
// after
#[derive(ProtoNew)]
struct Column {
    index: u32,
    name: String,
}
Defensive patterns

Strategy: validation

Validate before calling

// Compile-time: the derive itself is the guard; prefer validating struct shape in CI
// cargo check fails with this message when applied to tuple/unit structs

Prevention

When it happens

Trigger: Adding `#[derive(ProtoNew)]` to a tuple struct like `struct Foo(u32);` or a unit struct like `struct Foo;`.

Common situations: Copy-pasting the derive onto protos/enums-as-newtypes or wrapper tuple structs; refactoring a named-field struct into a tuple struct while keeping the derive.

Related errors


AI-assisted analysis of dbt-labs/dbt-core@0267ce9170 (2026-09-07). Data as JSON: /api/errors/26b60b16cbc7553e. Report an issue: GitHub.