vectordotdev/vector · error
field should be named
Error message
field should be named
What it means
This panic fires in vector-config-macros when generating a JSON schema for a named-field enum variant whose field unexpectedly has no identifier (i.e. a positional/tuple field reached the named-variant code path). The macro calls `field.ident().expect("field should be named")` because by that point the variant has been classified as a struct-style (named) variant, so every field must have a name. It is a derive-time internal invariant panic, not a runtime error in user code.
Solutions
- Check the enum variant that fails to derive: it must be a true named-field variant (`Variant { field: Type }`) for this code path
- Inspect generate_enum_variant_schema's variant classification so tuple/newtype fields go to generate_enum_newtype_struct_variant_schema instead
- If it is a macro bug, add an explicit shape check before calling field.ident() and emit a syn::Error with a span instead of expect()
Example fix
// before
let field_name = field.ident().expect("field should be named");
// after
let field_name = field.ident().ok_or_else(|| {
syn::Error::new(field.span(), "expected a named field on an enum struct variant")
.to_compile_error()
})?; Defensive patterns
Strategy: validation
Validate before calling
// In the macro, before calling ident():
if field.ident().is_none() {
return syn::Error::new(field.span(), "expected named field on struct variant").to_compile_error();
} Type guard
fn is_named_field(f: &syn::Field) -> bool { f.ident.is_some() } Prevention
- Keep variant classification (named vs tuple vs unit) centralized in one match in generate_enum_variant_schema
- Emit syn::Error with spans instead of expect() in proc-macro code paths
- Add macro unit tests covering all enum variant shapes
When it happens
Trigger: Deriving `Configurable` on an enum whose variant is dispatched to `generate_enum_struct_named_variant_schema` while a field carries no identifier — e.g. an inconsistency in the syn-derived `Variant` data or a macro-internal bug in variant classification (a tuple/newtype-style field routed into the named-field generator).
Common situations: Contributing to the vector-config derive macros and accidentally routing tuple-variant fields through the named-variant path; changing variant-shape detection logic and breaking the invariant that struct variants only contain named fields.
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
- must exist
- #[derive(NamedInternalEvent)] can only be used with structs
- a record with a next ID must have an event count
- a valid HTTP/1 URI is valid as an HTTP URI
- a validated HTTP endpoint is a valid `http 1` URI
AI-assisted analysis of vectordotdev/vector@bdb87aeaa4 (2026-09-16).
Data as JSON: /api/errors/d948b0d93072d83b.
Report an issue: GitHub.
Appendix: source
Thrown at lib/vector-config-macros/src/configurable.rs:907
let mut names = unflattened_serialized_names(fields);
if let Some(tag) = enclosing_tag {
names.push(tag.to_owned());
}
names
}
fn generate_named_enum_field(
field: &Field<'_>,
sibling_keys: &[String],
) -> proc_macro2::TokenStream {
if field.required_one_of().is_some() {
return syn::Error::new(
field.span(),
"`required_one_of` is not supported on enum variant fields",
)
.to_compile_error();
}
let field_name = field.ident().expect("field should be named");
let field_ty = field.ty();
let field_already_contained = format!(
"schema properties already contained entry for `{field_name}`, this should not occur"
);
let field_key = field.name().to_string();
let field_schema = generate_struct_field(field, sibling_keys);
// Fields that have no default value are inherently required. Unlike fields on a normal
// struct, we can't derive a default value for an individual field because `serde`
// doesn't allow even specifying a default value for an enum overall, only structs.
let spanned_is_optional = quote_spanned! {field.span()=>
<#field_ty as ::vector_config::Configurable>::is_optional()
};
let maybe_field_required = if field.default_value().is_none() {
Some(quote! {
if !#spanned_is_optional {
if !required.insert(#field_key.to_string()) {View on GitHub (pinned to bdb87aeaa4)