vectordotdev/vector · error · syn::Error

`required_one_of` is not supported on newtype struct fields

Error message

`required_one_of` is not supported on newtype struct fields

What it means

Same family as the tuple-struct check: `#[configurable]` rejects `required_one_of` on newtype struct fields. A newtype struct has a single unnamed field, so the 'at least one of several keys' schema concept cannot be represented and the macro emits a compile error.

Solutions

  1. Remove the `required_one_of` attribute from the newtype's inner field.
  2. Put `required_one_of` on the enclosing named struct's fields instead.
  3. Redefine the type as a named struct if one-of validation between fields is needed.

Example fix

// before
#[configurable]
struct Endpoint(#[configurable(required_one_of = ["host"])] String);

// after
#[configurable]
struct Endpoint {
    #[configurable(required_one_of = ["host", "address"])]
    host: String,
}
Defensive patterns

Strategy: validation

Validate before calling

// keep newtypes attribute-free: #[configurable(transparent)] where possible

Prevention

When it happens

Trigger: Applying `#[configurable]` to a newtype struct like `struct Port(u16);` whose inner field is annotated with `required_one_of`.

Common situations: Wrapping a primitive for type safety (newtype pattern) and blindly carrying over field attributes from the original named struct.

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/81324a790aede998. Report an issue: GitHub.

Appendix: source

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

        // 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)*

            Ok(::vector_config::schema::generate_tuple_schema(&subschemas))
        }
    }
}

fn build_newtype_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 newtype struct fields",
            )
            .to_compile_error();
        }
    }

    // Map the fields normally, but we should end up with a single field at the end.
    let mut 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(|field| generate_struct_field(field, &[]))
        .collect::<Vec<_>>();

    if mapped_fields.len() != 1 {
        panic!("newtype structs should never have more than one field");
    }

View on GitHub (pinned to bdb87aeaa4)