pydantic/monty · error · syn::Error

`varargs` fields must be `Vec<Value>` — coerce elements in t

Error message

`varargs` fields must be `Vec<Value>` — coerce elements in the function body

What it means

A compile-time validation error from the `FromArgs` derive: a `#[from_args(varargs)]` field (Python's `*args`) must have type `Vec<Value>`. Elements are bound raw, without conversion, so that CPython's error ordering can be reproduced by coercing in the function body.

Source

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

            if field.default.is_some() {
                seen_positional_default = true;
            } else if seen_positional_default {
                return Err(syn::Error::new(
                    field.ident.span(),
                    "required positional fields must come before positional fields with \
                     defaults — matching Python signatures, and relied on by the runtime \
                     binder's fast path",
                ));
            }
        }

        // Raw binding is deliberately separate from conversion (that split is
        // what reproduces CPython's error orderings), so `*args` elements are
        // handed over unconverted.
        if let Some(idx) = self.varargs_idx
            && !is_vec_of_value(&self.fields[idx].ty)
        {
            return Err(syn::Error::new(
                self.fields[idx].ident.span(),
                "`varargs` fields must be `Vec<Value>` — coerce elements in the function body",
            ));
        }

        // The runtime binder's fast paths return before the aggregated
        // missing-keyword check runs, so a required kw_only slot could slip
        // through binding unfilled and later surface `Bound::require`'s
        // positional wording. No current signature needs one; reject until
        // the fast paths learn to check for them.
        if let Some(field) = self
            .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 \

View on GitHub (pinned to adc986b362)

Solutions

  1. Change the field type to `Vec<Value>`
  2. Coerce each element in the function body after `from_args` (e.g. with `value_to_u64`), raising the appropriate error in CPython's order
  3. Use fixed named fields with `FromValue` types if element conversion should be automatic

Example fix

// before
#[derive(FromArgs)]
struct Args {
    #[from_args(varargs)]
    nums: Vec<u64>,
}
// after
#[derive(FromArgs)]
struct Args {
    #[from_args(varargs)]
    nums: Vec<Value>,
}
// then in body: nums.into_iter().map(|v| value_to_u64(v)).collect::<Result<Vec<_>,_>>()
Defensive patterns

Strategy: validation

Validate before calling

#[derive(FromArgs)]
struct Args { #[from_args(varargs)] rest: Vec<Value> } // only legal varargs type

Prevention

When it happens

Trigger: Declaring a field annotated `#[from_args(varargs)]` with any type other than `Vec<Value>`, e.g. `Vec<String>` or `Vec<u64>`.

Common situations: Trying to make the macro do per-element type conversion for `*args`; copying a `Vec<T>` pattern from a non-varargs field; porting a Rust function signature directly into the args struct.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


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