{"record":{"id":"5915613aa49824d2","repo":"vectordotdev/vector","slug":"derive-namedinternalevent-can-only-be-used-wit","errorCode":null,"errorMessage":"#[derive(NamedInternalEvent)] can only be used with structs","messagePattern":"#\\[derive\\(NamedInternalEvent\\)\\] can only be used with structs","errorType":"validation","errorClass":"syn::Error","httpStatus":null,"severity":"error","filePath":"lib/vector-common-macros/src/internal_event.rs","lineNumber":10,"sourceCode":"use proc_macro::TokenStream;\nuse quote::quote;\nuse syn::{Data, DeriveInput, parse_macro_input, spanned::Spanned};\n\n/// Implements `NamedInternalEvent` for structs via `#[derive(NamedInternalEvent)]`.\npub fn derive_impl_named_internal_event(item: TokenStream) -> TokenStream {\n    let input = parse_macro_input!(item as DeriveInput);\n\n    if !matches!(input.data, Data::Struct(_)) {\n        return syn::Error::new(\n            input.span(),\n            \"#[derive(NamedInternalEvent)] can only be used with structs\",\n        )\n        .to_compile_error()\n        .into();\n    }\n\n    let DeriveInput {\n        ident, generics, ..\n    } = input;\n    let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();\n\n    // Use a path that works from both vector-common (crate::internal_event)\n    // and from other crates using vector-lib (vector_lib::internal_event).\n    // For crates that don't depend on vector-lib but do depend on vector-common,\n    // we use vector_common::internal_event.\n    let pkg_name = std::env::var(\"CARGO_PKG_NAME\").unwrap_or_default();\n    let internal_event_path = if pkg_name == \"vector-common\" {","sourceCodeStart":1,"sourceCodeEnd":28,"githubUrl":"https://github.com/vectordotdev/vector/blob/3708c39b12a93212ed8b8d7510b4cc7769cb5864/lib/vector-common-macros/src/internal_event.rs#L1-L28","documentation":"`NamedInternalEvent` is a derive macro in vector-common-macros that implements the trait only for structs, because it derives the event name from struct fields/ident. The macro inspects `DeriveInput.data` and emits this compile error when the derive is placed on an enum or union. It is a pure compile-time diagnostic with correct span information on the offending type.","triggerScenarios":"Writing `#[derive(NamedInternalEvent)]` on an `enum` or `union` while adding internal event instrumentation to Vector or a component crate.","commonSituations":"Contributors instrumenting new internal events who model them as enums (e.g. one enum with variants per severity) instead of one struct per event; copy-pasting a derive list onto a new type declaration.","solutions":["Model each internal event as its own unit/field struct and put the derive on the structs.","If an enum grouping is desired, derive on plain structs and group them in a separate module instead.","Check nearby usages (e.g. `rg 'NamedInternalEvent' src/`) for the accepted struct shape and copy it."],"exampleFix":"// before\n#[derive(NamedInternalEvent)]\nenum SocketEvents {\n    Read,\n    Write,\n}\n\n// after\n#[derive(NamedInternalEvent)]\nstruct SocketReadError;\n\n#[derive(NamedInternalEvent)]\nstruct SocketWriteError;","handlingStrategy":"validation","validationCode":"// Compile-time by design: the error only fires on enums/unions.\n// CI guard: reject derives on non-structs via a lint/test that greps usage:\n// rg -n '#[derive(.*NamedInternalEvent.*)]' --before-context 2 | check next item is struct","typeGuard":null,"tryCatchPattern":null,"preventionTips":["One struct per internal event; never enums/unions.","Copy a working derive block from an existing internal-events module when contributing.","Read the error span — it points at the exact type declaration."],"tags":["rust","proc-macro","derive","compile-error","vector"],"backgroundTag":"derive-macro-misuse","analyzedSha":"3708c39b12a93212ed8b8d7510b4cc7769cb5864","analyzedAt":"2026-08-20T07:02:18.786Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}