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
- Move `#[derive(NamedInternalEvent)]` to a struct instead of the enum/union
- If you need an enum of events, wrap the derive on each struct variant's payload type or implement `NamedInternalEvent` manually for the enum
- 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
- Run cargo check immediately after adding a derive so macro errors surface on the right item
- Never attach event derives to enums; implement the trait by hand for sum types
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
- field should be named
- must exist
- component cannot have multiple names defined
- component must have a name defined (e.g…
- {}
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)