pydantic/monty · error · syn::Error
`at_most_total` cannot be combined with `style = def` or `st
Error message
`at_most_total` cannot be combined with `style = def` or `style = unpack` — the total pre-count models `PyArg_ParseTupleAndKeywords`-family C parsers
What it means
The `at_most_total` flag was set on a `#[derive(FromArgs)]` struct whose style is `def` or `unpack`. `at_most_total` emits an up-front total-argument-count check that mirrors the `PyArg_ParseTupleAndKeywords` family of C parsers; the `def` and `unpack` styles follow different parser models where that pre-count does not exist, so the combination is rejected rather than silently ignored.
Source
Thrown at crates/monty-macros/src/from_args.rs:241
signature can never raise too-many-positional, so the style has no effect");
}
}
Style::Unpack => {
if self.fields.iter().any(|f| matches!(f.kind, FieldKind::PosOrKeyword)) {
return err("`style = unpack` models a positional-only `PyArg_UnpackTuple` \
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 \View on GitHub (pinned to adc986b362)
Solutions
- Remove `at_most_total` from the def- or unpack-style struct.
- If the total pre-count check is required, keep the default `clinic` style (or use the `c`/`c_named` family), which supports `at_most_total`.
- If you need both def-binding and a max-count check, enforce the count manually in the function body.
Example fix
// before
#[derive(FromArgs)]
#[from_args(style = "def", at_most_total)]
struct Args { a: Value }
// after
#[derive(FromArgs)]
#[from_args(style = "def")]
struct Args { a: Value } Defensive patterns
Strategy: validation
Validate before calling
// at_most_total is only valid for clinic/c/c_named styles:
fn at_most_total_allowed(style: &str) -> bool {
matches!(style, "clinic" | "c" | "c_named")
} Prevention
- Keep at_most_total paired only with the C-parser-family styles it models.
- When changing a struct's style, re-check every modifier flag in the same edit.
When it happens
Trigger: Compiling `#[derive(FromArgs)] #[from_args(style = "def", at_most_total)]` or the same with `style = "unpack"`. Checked in `Signature::validate` (crates/monty-macros/src/from_args.rs:239-245).
Common situations: Copying the `at_most_total` attribute from a C-family struct while changing style to `def` or `unpack`; cargo-culting the full attribute set when adapting a handler between styles.
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 `varargs` or `varkwa
AI-assisted analysis of pydantic/monty@adc986b362 (2026-09-13).
Data as JSON: /api/errors/54798dea63fea2cd.
Report an issue: GitHub.