vectordotdev/vector · error

named struct fields must always have an ident

Error message

named struct fields must always have an ident

What it means

`generate_named_struct_field` unwraps `field.ident()` with an expect because it is only invoked for named-field structs, where serde always provides an identifier. A None here means the derive generated a call for a field that is not a named field — a violation of the macro's internal dispatch invariants.

Solutions

  1. Verify the struct uses named fields (this path is not for tuple structs); use the appropriate derive path for newtype/tuple structs
  2. Align vector-config-macros and serde_derive versions and rebuild (cargo clean)
  3. If reproducible, minimize the failing struct definition and file an issue
Defensive patterns

Strategy: validation

Prevention

When it happens

Trigger: Expanding `#[configurable]` on a named struct when `build_named_struct_generate_schema_fn` processes a `Field` whose ident is None (i.e. a tuple/newtype field reached the named-struct code path).

Common situations: Unreachable in normal use; seen only with proc-macro bugs, hand-written token streams passed into the macro helpers, or dependency version mismatches after upgrades.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


AI-assisted analysis of vectordotdev/vector@bdb87aeaa4 (2026-09-16). Data as JSON: /api/errors/db732f695a31769f. Report an issue: GitHub.

Appendix: source

Thrown at lib/vector-config-macros/src/configurable.rs:275

        let mut subschema = #spanned_generate_schema;
    }
}

#[derive(Clone)]
struct RequiredOneOf {
    group: String,
    members: Vec<String>,
}

fn generate_named_struct_field(
    container: &Container<'_>,
    field: &Field<'_>,
    required_one_of: Option<RequiredOneOf>,
    sibling_keys: &[String],
) -> proc_macro2::TokenStream {
    let field_name = field
        .ident()
        .expect("named struct fields must always have an ident");
    let field_schema_ty = get_field_schema_ty(field);
    let field_already_contained = format!(
        "schema properties already contained entry for `{field_name}`, this should not occur"
    );
    let field_key = field.name();

    let field_schema = generate_struct_field(field, sibling_keys);

    // Inject docs::required_one_of and docs::required_one_of_group metadata so the CUE doc
    // builder can render the mutual exclusivity constraint and its group name.
    let inject_required_one_of = required_one_of.map(|RequiredOneOf { group, members }| {
        let member_lits: Vec<syn::LitStr> = members
            .iter()
            .map(|m| syn::LitStr::new(m, proc_macro2::Span::call_site()))
            .collect();
        quote! {
            if let Some(meta) = subschema.extensions.get_mut("_metadata") {
                if let Some(obj) = meta.as_object_mut() {

View on GitHub (pinned to bdb87aeaa4)