vectordotdev/vector · error · syn::Error

`required_one_of` is not supported on tuple struct fields

Error message

`required_one_of` is not supported on tuple struct fields

What it means

The `#[configurable]` derive macro rejects `required_one_of` on tuple struct fields. This attribute only makes sense for named struct fields, where the schema can express 'one of these named keys must be present'. For tuple structs the macro bails out at compile time with a syn::Error converted to a compile_error! token stream.

Solutions

  1. Remove `required_one_of` from the tuple struct field.
  2. Convert the tuple struct into a named struct if you genuinely need one-of semantics among fields.
  3. Move `required_one_of` to an enum or a named struct variant that can express it in schema metadata.

Example fix

// before
#[configurable]
struct Foo(#[configurable(required_one_of = ["a"])] u64);

// after
#[configurable]
struct Foo {
    #[configurable(required_one_of = ["a", "b"])]
    value: u64,
}
Defensive patterns

Strategy: validation

Validate before calling

// compile-time: assert the struct is a named struct when using required_one_of
struct AssertNamedStruct;
const _: () = { let _ = AssertNamedStruct; }; // remove required_one_of from tuple fields

Prevention

When it happens

Trigger: Annotating a tuple struct (e.g. `struct Wrapper(u64);`) with `#[configurable]` while one of its positional fields carries `#[configurable(required_one_of = [...])]` or the struct-level equivalent that lands on fields.

Common situations: Copying a `required_one_of` annotation from a named config struct into a tuple/newtype wrapper, or applying the derive to an auto-generated tuple struct that inherited field attributes.

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/3db6fb6a0c4fb2aa. Report an issue: GitHub.

Appendix: source

Thrown at lib/vector-config-macros/src/configurable.rs:567

                // That's kind of useless, and ends up as noise in the schema, so if we didn't have
                // any of our own unflattened properties, then steal the first flattened subschema
                // and swap our main schema for it before flattening things overall.
                if !had_unflatted_properties {
                    schema = flattened_subschemas.remove(0);
                }

                ::vector_config::schema::convert_to_flattened_schema(&mut schema, flattened_subschemas);
            }

            Ok(schema)
        }
    }
}

fn build_tuple_struct_generate_schema_fn(fields: &[Field<'_>]) -> proc_macro2::TokenStream {
    for field in fields.iter() {
        if field.required_one_of().is_some() {
            return syn::Error::new(
                field.span(),
                "`required_one_of` is not supported on tuple struct fields",
            )
            .to_compile_error();
        }
    }

    let mapped_fields = fields
        .iter()
        // Don't map this field if it's marked to be skipped for both serialization and deserialization.
        .filter(|field| field.visible())
        .map(generate_tuple_struct_field);

    quote! {
        fn generate_schema(schema_gen: &::std::cell::RefCell<::vector_config::schema::SchemaGenerator>) -> std::result::Result<::vector_config::schema::SchemaObject, ::vector_config::GenerateError> {
            let mut subschemas = ::std::collections::Vec::new();

            #(#mapped_fields)*

View on GitHub (pinned to bdb87aeaa4)