vectordotdev/vector · error · syn::Error

component cannot have multiple names defined

Error message

component cannot have multiple names defined

What it means

The `ComponentName` derive requires exactly one component name. After validating the collected names, it checks `component_names.len() > 1` and fails compilation when more than one helper attribute supplied a name. Ambiguous naming would make config parsing and the component registry non-deterministic, so it is rejected at compile time.

Solutions

  1. Remove all but one `#[component_name("...")]` attribute from the struct
  2. Keep the attribute matching the component's actual kind (source/sink/transform) and delete the others
  3. If inheritance from a wrapper macro is intended, remove the manual attribute and let the macro supply the name

Example fix

// before
#[component_name("old_name")]
#[component_name("new_name")]
struct MySourceConfig;
// after
#[component_name("new_name")]
struct MySourceConfig;
Defensive patterns

Strategy: validation

Validate before calling

grep -n '#\[component_name(' my_component.rs  # must list exactly one line

Prevention

When it happens

Trigger: Applying two or more `#[component_name("...")]`-style helper attributes (or any recognized component-name attributes, e.g. source/sink/transform variants) to a single derived struct, then compiling.

Common situations: Copy-pasting an attribute from a similar component and leaving both; switching component kind but keeping the old attribute; macro expansion from another macro injecting an extra name attribute.

Understand the failure class

Background: Conflicting config options: "cannot be used together" — configuration validation errors across open-source libraries — this error's family across 162 libraries.

Related errors


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

Appendix: source

Thrown at lib/vector-config-macros/src/component_name.rs:82

            main_error.combine(error);
        }

        return main_error.into_compile_error().into();
    }

    // Any component names we have now have been validated, so we just need to check and make sure
    // we actually have one, and only one, and spit out the correct errors otherwise.
    if component_names.is_empty() {
        return Error::new(
            ident.span(),
            "component must have a name defined (e.g. `#[component_name(\"foobar\")]`)",
        )
        .into_compile_error()
        .into();
    }

    if component_names.len() > 1 {
        return Error::new(ident.span(), "component cannot have multiple names defined")
            .into_compile_error()
            .into();
    }

    let component_name = component_names.remove(0);

    // We have a single, valid component name, so let's actually spit out our derive.
    let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
    let derived = quote! {
        impl #impl_generics #ident #ty_generics #where_clause {
            pub(super) const NAME: &'static str = #component_name;
        }

        impl #impl_generics ::vector_config::NamedComponent for #ident #ty_generics #where_clause {
            fn get_component_name(&self) -> &'static str {
                #component_name
            }
        }

View on GitHub (pinned to bdb87aeaa4)