pydantic/monty · error · syn::Error

only one `#[from_args(varkwargs)]` field is allowed

Error message

only one `#[from_args(varkwargs)]` field is allowed

What it means

A compile-time error from the `FromArgs` derive macro. Python allows at most one `**kwargs` parameter, so the macro allows at most one field tagged `#[from_args(varkwargs)]` per struct. A second tagged field cannot map to a Python signature and is rejected.

Source

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

                if seen_varargs {
                    return Err(syn::Error::new(
                        field.ident.span(),
                        "only one `#[from_args(varargs)]` field is allowed",
                    ));
                }
                if seen_kw_only {
                    return Err(syn::Error::new(
                        field.ident.span(),
                        "`varargs` cannot appear after keyword-only fields — Python has no \
                         signature form with `*args` following keyword-only parameters",
                    ));
                }
                seen_varargs = true;
                varargs_idx = Some(idx);
            }
            FieldKind::Varkwargs => {
                if seen_varkwargs {
                    return Err(syn::Error::new(
                        field.ident.span(),
                        "only one `#[from_args(varkwargs)]` field is allowed",
                    ));
                }
                seen_varkwargs = true;
                varkwargs_idx = Some(idx);
            }
        }

        if matches!(field.kind, FieldKind::PosOnly | FieldKind::PosOrKeyword) {
            pos_counter += 1;
            field.pos_index = Some(pos_counter);
        }
        if !matches!(field.kind, FieldKind::Varargs | FieldKind::Varkwargs) {
            field.slot_index = Some(slot_counter);
            slot_counter += 1;
        }
    }

View on GitHub (pinned to adc986b362)

Solutions

  1. Keep a single `#[from_args(varkwargs)]` field (typically a dict/kwargs type) and do any key filtering in the function body
  2. Remove the `varkwargs` attribute from the duplicate field if it is actually a fixed keyword parameter
  3. Change the duplicate to `#[from_args(kw_only)]` if it represents a specific named keyword argument

Example fix

// before
#[derive(FromArgs)]
#[from_args(name = "f"])
struct FArgs {
    #[from_args(varkwargs)]
    kwargs: Value,
    #[from_args(varkwargs)]
    extra: Value,
}

// after
#[derive(FromArgs)]
#[from_args(name = "f"])
struct FArgs {
    #[from_args(varkwargs)]
    kwargs: Value,
}
Defensive patterns

Strategy: validation

Validate before calling

// At most one varkwargs field per struct.
fn at_most_one_varkwargs(kinds: &[&str]) -> bool {
    kinds.iter().filter(|k| **k == "varkwargs").count() <= 1
}

Prevention

When it happens

Trigger: Deriving `FromArgs` on a struct containing two or more fields annotated `#[from_args(varkwargs)]`.

Common situations: Merging two arg structs that each carried their own kwargs field, or copy-pasting a kwargs field to split keyword handling into two buckets.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


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