pydantic/monty · error · syn::Error

`default` and `static_string` cannot be applied to `varargs`

Error message

`default` and `static_string` cannot be applied to `varargs` / `varkwargs` fields — they configure a named parameter slot, which collector fields don't own

What it means

A compile-time validation error from the `FromArgs` derive: `#[from_args(default)]` and `#[from_args(static_string)]` configure a single named parameter slot, so they are rejected on `varargs`/`varkwargs` collector fields, where they would be silently ignored.

Source

Thrown at crates/monty-macros/src/from_args.rs:337

            .fields
            .iter()
            .find(|f| matches!(f.kind, FieldKind::KwOnly) && f.default.is_none())
        {
            return Err(syn::Error::new(
                field.ident.span(),
                "keyword-only fields must have a `default` — the runtime binder's fast \
                 paths skip the aggregated missing-keyword check, so a required \
                 keyword-only parameter would report the wrong error; extend the binder \
                 before allowing this",
            ));
        }

        // `default` / `static_string` describe a named parameter slot; on the
        // collector fields they would be silently dead configuration.
        for idx in [self.varargs_idx, self.varkwargs_idx].into_iter().flatten() {
            let field = &self.fields[idx];
            if field.default.is_some() || field.static_string.is_some() {
                return Err(syn::Error::new(
                    field.ident.span(),
                    "`default` and `static_string` cannot be applied to `varargs` / \
                     `varkwargs` fields — they configure a named parameter slot, which \
                     collector fields don't own",
                ));
            }
        }

        Ok(())
    }

    fn render(&self) -> TokenStream {
        let struct_ident = &self.struct_ident;
        // Dedicated owning-slots struct: holds the raw `Bound` returned by the
        // runtime binder plus one typed `Option` per named field. A `DropGuard`
        // around it centralises error-path cleanup in one `DropWithContext` impl,
        // so every conversion site is a plain `?`.
        let slots_struct_ident = format_ident!("__{}Slots", struct_ident);

View on GitHub (pinned to adc986b362)

Solutions

  1. Remove the `default`/`static_string` attribute from the collector field — it is always initialized empty
  2. Apply `default`/`static_string` only to named (positional or kw-only) fields
  3. Handle any 'missing' fallback in the function body instead

Example fix

// before
#[derive(FromArgs)]
struct Args {
    #[from_args(varargs, default)]
    extra: Vec<Value>,
}
// after
#[derive(FromArgs)]
struct Args {
    #[from_args(varargs)]
    extra: Vec<Value>, // always present, empty when no args
}
Defensive patterns

Strategy: validation

Validate before calling

// collectors (varargs/varkwargs) accept no default/static_string attributes
#[from_args(varargs)] extra: Vec<Value>,

Prevention

When it happens

Trigger: Annotating a `#[from_args(varargs)]` or `#[from_args(varkwargs)]` field with `default` or `static_string`, e.g. `#[from_args(varkwargs, default)] options: ...`.

Common situations: Copy-pasting attribute lists from a normal field onto a collector field; trying to express 'default to empty collection' without realizing collectors already start empty.

Understand the failure class

Background: Conflicting config options: "cannot be used together" — configuration validation errors across open-source libraries — this error's family across 162 libraries.

Related errors


AI-assisted analysis of pydantic/monty@adc986b362 (2026-09-13). Data as JSON: /api/errors/4a83e0c42bc8ff07. Report an issue: GitHub.