vectordotdev/vector · error
#tag_already_contained
Error message
#tag_already_contained
What it means
This is a compile-time panic emitted by the generated schema-building code of the `Configurable` derive macro. When generating the schema for an adjacently-tagged (or similarly tagged) enum variant, the macro inserts a synthetic `tag` property into the variant's `properties` and `required` sets. If the variant's own fields already contain a property with the same name as the tag key, the insertion collides and the macro panics, because the generated JSON Schema would be self-contradictory (two definitions for one property name).
Solutions
- Rename the conflicting field inside the variant struct so it no longer matches the tag key
- Change the enum-level tag name via the tag attribute to something that does not collide with any variant field
- Prefix or restructure the variant's fields so the tag property is generated only by the macro
Example fix
// before
#[configurable(tag = "type")]
enum Source {
A { type: String, port: u16 },
}
// after
#[configurable(tag = "type")]
enum Source {
A { kind: String, port: u16 },
} Defensive patterns
Strategy: validation
Validate before calling
// Before deriving Configurable on a tagged enum, check variant fields against the tag:
fn tag_conflicts<'a>(tag: &str, variant_fields: impl IntoIterator<Item = &'a str>) -> bool {
variant_fields.into_iter().any(|f| f == tag)
}
// assert!(!tag_conflicts("type", ["type", "port"]), "field collides with tag key"); Prevention
- Keep the tag key name (e.g. "type", "kind") reserved — never use it as a field name in variant structs
- Grep the enum's variants for the tag name after changing any tag attribute
- Standardize tag keys per crate to reduce collision chance
When it happens
Trigger: Deriving `Configurable` on an enum annotated with an adjacent/internal tag (e.g. `#[configurable(tag = "type")]`) where one of the variant structs already declares a field whose name equals the tag key (`type`), so `properties.insert(tag)` returns `Some` or `required.insert` returns `false` during `generate_enum_variant_schema`.
Common situations: Adding a new enum variant whose struct reuses the tag field name; renaming a tag attribute to collide with an existing variant field; copying a variant definition from another enum that uses a different tag name.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- No description provided for
- Tried to overwrite metadata flag
- Tried to set metadata flag
- tuple variants should be rejected during AST parsing
- component cannot have multiple names defined
AI-assisted analysis of vectordotdev/vector@bdb87aeaa4 (2026-09-16).
Data as JSON: /api/errors/0aea08ddee58d830.
Report an issue: GitHub.
Appendix: source
Thrown at lib/vector-config-macros/src/configurable.rs:1129
// { "field_using_enum": { "<tag>": "VariantName", "some_field": false } }
//
// # Struct form with unnamed field is not valid here. See comments below.
//
// # Unit form.
// { "field_using_enum": { "<tag>": "VariantName" } }
Tagging::Internal { tag } => match variant.style() {
Style::Struct => {
let tag_already_contained = format!(
"enum tag `{tag}` already contained as a field in variant; tag cannot overlap with any fields in any variant"
);
// Just generate the tag field directly and pass it along to be included in the
// struct schema.
let tag_schema = generate_enum_variant_tag_schema(variant);
let tag_field = quote! {
{
if let Some(_) = properties.insert(#tag.to_string(), #tag_schema) {
panic!(#tag_already_contained);
}
if !required.insert(#tag.to_string()) {
panic!(#tag_already_contained);
}
}
};
generate_enum_struct_named_variant_schema(
variant,
Some(tag_field),
Some(tag),
false,
)
}
Style::Tuple => panic!("tuple variants should be rejected during AST parsing"),
Style::Newtype => {
// We have to delegate viability to `serde`, essentially, because using internal tagging for a newtype
// variant is only possible when the inner field is a struct or map, and we can't access that type ofView on GitHub (pinned to bdb87aeaa4)