pydantic/monty · error · syn::Error
`at_most_total` cannot be combined with `varargs` or `varkwa
Error message
`at_most_total` cannot be combined with `varargs` or `varkwargs` — the up-front total-count check is only meaningful for signatures with a fixed maximum
What it means
The `at_most_total` flag was set on a `#[derive(FromArgs)]` struct that also has a `varargs` or `varkwargs` field. The up-front total-count check only makes sense for signatures with a fixed maximum arity; with `*args`/`**kwargs` there is no upper bound to pre-check, so the combination is a compile-time error.
Source
Thrown at crates/monty-macros/src/from_args.rs:247
signature — every positional field must be `pos_only`");
}
if self.varargs_idx.is_some() || self.varkwargs_idx.is_some() {
return err("`style = unpack` cannot be combined with `varargs` or `varkwargs` \
— it models a fixed positional min..max range");
}
}
Style::Clinic | Style::C | Style::CNamed => {}
}
if self.at_most_total {
if matches!(self.style, Style::Def | Style::Unpack) {
return err(
"`at_most_total` cannot be combined with `style = def` or `style = unpack` \
— the total pre-count models `PyArg_ParseTupleAndKeywords`-family C parsers",
);
}
if self.varargs_idx.is_some() || self.varkwargs_idx.is_some() {
return err("`at_most_total` cannot be combined with `varargs` or `varkwargs` \
— the up-front total-count check is only meaningful for \
signatures with a fixed maximum");
}
}
if self.vectorcall && !(self.at_most_total && self.style == Style::Clinic) {
return err("`vectorcall` requires the default `clinic` style plus `at_most_total` \
— it models a `tp_vectorcall` fast path in front of a clinic parser");
}
if self.kwarg_error_name.is_some() && !matches!(self.style, Style::Def | Style::Clinic | Style::Unpack) {
return err("`kwarg_error_name` is only meaningful with `style = def`, the default \
`clinic` style, or `style = unpack` (where it names the function in the \
`takes no keyword arguments` error) — the C families defer unknown-kwarg \
errors past binding");
}
if self.kwargs_not_supported_yet {View on GitHub (pinned to adc986b362)
Solutions
- Remove `at_most_total` from the struct.
- If you need the pre-count check, drop the varargs/varkwargs field and give the struct a fixed set of fields.
- If a cap on the number of arguments is truly needed, enforce it manually in the function body after collection.
Example fix
// before
#[derive(FromArgs)]
#[from_args(at_most_total)]
struct Args { a: Value, #[from_args(varargs)] rest: Vec<Value> }
// after
#[derive(FromArgs)]
struct Args { a: Value, #[from_args(varargs)] rest: Vec<Value> } Defensive patterns
Strategy: validation
Validate before calling
fn at_most_total_needs_fixed_max(has_varargs: bool, has_varkwargs: bool) -> bool {
!has_varargs && !has_varkwargs
} Prevention
- A pre-count check needs an upper bound; any struct with *args/**kwargs cannot have one.
- If a cap is needed on variadic input, enforce it in the function body.
When it happens
Trigger: Compiling `#[derive(FromArgs)] #[from_args(at_most_total)] struct Args { a: i64, #[from_args(varargs)] rest: Vec<Value> }` or with a `varkwargs` field. Checked in `Signature::validate` (crates/monty-macros/src/from_args.rs:246-250).
Common situations: Generalizing a fixed-arity C-family handler to accept `*args` while leaving the old `at_most_total` flag; mixing attributes from two structs with different shapes.
Related errors
- `bad_arg`/`bad_arg_named` cannot be combined with `style = d
- `style = def` cannot be combined with `varargs` — a `*args`
- `style = unpack` models a positional-only `PyArg_UnpackTuple
- `style = unpack` cannot be combined with `varargs` or `varkw
- `at_most_total` cannot be combined with `style = def` or `st
AI-assisted analysis of pydantic/monty@adc986b362 (2026-09-13).
Data as JSON: /api/errors/c3ead5577bf3509f.
Report an issue: GitHub.