vectordotdev/vector · error · syn::Error

{component_type}s must have a name specified (e.g. `{compone

Error message

{component_type}s must have a name specified (e.g. `{component_type_attr}("my_component")`)

What it means

For the `#[configurable_component(...)]` helper attributes (marker forms like `source_component`, `sink_component`, `transform_component`), the macro rebuilds the user-facing attribute name and requires the attribute to be a list with inner tokens — `#[source("my_source")]`. If the attribute has no list part at all (e.g. bare `#[source]`), this contextual compile error is returned, phrased with the reconstructed component type ("sources must have a name specified..."). It is the friendlier pre-check before arg parsing.

Source

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

            attrs::SOURCE_COMPONENT,
            attrs::TRANSFORM_COMPONENT,
            attrs::SECRETS_COMPONENT,
        ],
    ) {
        return Ok(None);
    }

    // Reconstruct the original attribute path (i.e. `source`) from our marker version of it (i.e.
    // `source_component`), so that any error message we emit is contextually relevant.
    let path_str = path_to_string(attr.path());
    let component_type_attr = path_str.replace("_component", "");
    let component_type = component_type_attr.replace('_', " ");

    // Make sure the attribute actually has inner tokens. If it doesn't, this means they forgot
    // entirely to specify a component name, and we want to give back a meaningful error that looks
    // correct when applied in the context of `#[configurable_component(...)]`.
    if attr.meta.require_list().is_err() {
        return Err(Error::new(
            attr.span(),
            format!(
                "{component_type}s must have a name specified (e.g. `{component_type_attr}(\"my_component\")`)"
            ),
        ));
    }

    // Now try and parse the helper attribute as a literal string, which is the only valid form.
    // After that, make sure it's actually valid according to our naming rules.
    attr.parse_args::<LitStr>()
        .map_err(|_| {
            Error::new(
                attr.span(),
                format!(
                    "expected a string literal for the {component_type} name (i.e. `{component_type_attr}(\"...\")`)"
                ),
            )
        })

View on GitHub (pinned to 3708c39b12)

Solutions

  1. Give the attribute its list form with a quoted literal name: `#[source("my_component")]`.
  2. Match the naming rules — a lowercase literal string (kebab/snake per the project's convention); anything non-literal produces the adjacent parse error.
  3. Compare against an existing component's attribute block and mirror the shape.

Example fix

// before
#[configurable_component(source)]
struct FileSourceConfig;

// after
#[configurable_component(source("file"))]
struct FileSourceConfig;
Defensive patterns

Strategy: validation

Validate before calling

// Compile-time enforced; correct form is a list attribute with a string literal:
// #[configurable_component(source("file"))]
// struct FileSourceConfig;

Prevention

When it happens

Trigger: Writing a component attribute without its parenthesized name: `#[source]` or `#[configurable_component(source)]` instead of `#[source("file")]` / `#[configurable_component(source("file"))]`. A non-list meta (key-value form `#[source = "x"]`) also fails `require_list` and lands here.

Common situations: New component authors forgetting the name string; IDE auto-complete inserting the bare attribute path; refactoring from older attribute syntax where the name lived elsewhere.

Related errors


AI-assisted analysis of vectordotdev/vector@3708c39b12 (2026-08-20). Data as JSON: /api/errors/34c2b7669298823d. Report an issue: GitHub.