pydantic/monty · error · syn::Error
`style = unpack` cannot be combined with `varargs` or `varkw
Error message
`style = unpack` cannot be combined with `varargs` or `varkwargs` — it models a fixed positional min..max range
What it means
A `#[derive(FromArgs)]` struct with `style = unpack` also declares a `varargs` (`*args`) or `varkwargs` (`**kwargs`) field. `unpack` models `PyArg_UnpackTuple`, a fixed positional min..max range; variadic collection is outside that model, so the macro rejects the combination at compile time.
Source
Thrown at crates/monty-macros/src/from_args.rs:232
match self.style {
Style::Def => {
if self.bad_arg.is_some() {
return err("`bad_arg`/`bad_arg_named` cannot be combined with `style = def` \
— CPython `def` binding never type-checks while binding; declare \
fields as raw `Value` and coerce in the function body");
}
if self.varargs_idx.is_some() {
return err("`style = def` cannot be combined with `varargs` — a `*args` \
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");
}View on GitHub (pinned to adc986b362)
Solutions
- Remove `style = "unpack"` and let the default `clinic` style parse; it supports varargs/varkwargs fields.
- If the signature really is fixed-width, drop the varargs/varkwargs field and enumerate the positional fields explicitly with `pos_only`.
Example fix
// before
#[derive(FromArgs)]
#[from_args(style = "unpack")]
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 unpack_is_fixed_arity(has_varargs: bool, has_varkwargs: bool) -> bool {
!has_varargs && !has_varkwargs
} Prevention
- Treat style = "unpack" as strictly fixed min..max positional; variadic fields require another style.
- Check the README style table when adding varargs/varkwargs fields to an existing struct.
When it happens
Trigger: Compiling `#[derive(FromArgs)] #[from_args(style = "unpack")] struct Args { a: i64, #[from_args(varargs)] rest: Vec<Value> }` (or a `varkwargs` field). Checked in `Signature::validate` (crates/monty-macros/src/from_args.rs:231-234).
Common situations: Adding a catch-all `*args` field to an existing unpack-style struct while generalizing a builtin; confusing `unpack` (fixed tuple unpack) with general C-style variadic parsing.
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
- `at_most_total` cannot be combined with `style = def` or `st
- `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/3c616a4581e9b160.
Report an issue: GitHub.