vectordotdev/vector · error · syn::Error

#[derive(NamedInternalEvent)] can only be used with structs

Error message

#[derive(NamedInternalEvent)] can only be used with structs

What it means

This is a compile-time diagnostic from the `NamedInternalEvent` derive macro in vector-common-macros. The macro generates an implementation of the `NamedInternalEvent` trait, which requires a named struct's fields to build the event name. Applying the derive to an enum, union, or unit struct is rejected because the macro's codegen only knows how to handle struct-shaped input (`Data::Struct`).

Solutions

  1. Move `#[derive(NamedInternalEvent)]` to a struct instead of the enum/union
  2. If you need an enum of events, wrap the derive on each struct variant's payload type or implement `NamedInternalEvent` manually for the enum
  3. If the item was converted from a struct to an enum, remove the derive and hand-write the trait impl

Example fix

// before
#[derive(NamedInternalEvent)]
enum EventKind { A, B }
// after
#[derive(NamedInternalEvent)]
struct EventKind { name: &'static str }
Defensive patterns

Strategy: validation

Validate before calling

fn assert_named_internal_event_target<T>() { let _ = std::marker::PhantomData::<T>; }
// Only attach the derive to `struct` items; enums/unions must impl the trait manually.

Prevention

When it happens

Trigger: Attaching `#[derive(NamedInternalEvent)]` to an `enum`, a `union`, or any non-struct item, then running `cargo build`/`cargo check`. The proc macro's `derive_impl_named_internal_event` parses the item as `DeriveInput` and matches `input.data`; any variant other than `Data::Struct(_)` returns `syn::Error` at the item's span.

Common situations: Refactoring a struct into an enum while leaving the derive attribute in place; copy-pasting the derive onto an enum of event variants; assuming the trait supports sum types like other event traits.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


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

Appendix: source

Thrown at lib/vector-common-macros/src/internal_event.rs:10

use proc_macro::TokenStream;
use quote::quote;
use syn::{Data, DeriveInput, parse_macro_input, spanned::Spanned};

/// Implements `NamedInternalEvent` for structs via `#[derive(NamedInternalEvent)]`.
pub fn derive_impl_named_internal_event(item: TokenStream) -> TokenStream {
    let input = parse_macro_input!(item as DeriveInput);

    if !matches!(input.data, Data::Struct(_)) {
        return syn::Error::new(
            input.span(),
            "#[derive(NamedInternalEvent)] can only be used with structs",
        )
        .to_compile_error()
        .into();
    }

    let DeriveInput {
        ident, generics, ..
    } = input;
    let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();

    // Use a path that works from both vector-common (crate::internal_event)
    // and from other crates using vector-lib (vector_lib::internal_event).
    // For crates that don't depend on vector-lib but do depend on vector-common,
    // we use vector_common::internal_event.
    let pkg_name = std::env::var("CARGO_PKG_NAME").unwrap_or_default();
    let internal_event_path = if pkg_name == "vector-common" {

View on GitHub (pinned to bdb87aeaa4)