pydantic/monty · error · syn::Error
positional-only fields must come before positional-or-keywor
Error message
positional-only fields must come before positional-or-keyword, varargs, and keyword-only fields
What it means
This is a compile-time error from the `FromArgs` derive macro in monty-macros. It fires when a struct field marked `#[from_args(pos_only)]` is declared after a positional-or-keyword field, a `varargs` field, or a keyword-only field. Python signatures require positional-only parameters to come first, so the derived binder rejects the struct definition rather than producing a signature Python could never express.
Source
Thrown at crates/monty-macros/src/from_args.rs:564
let mut varkwargs_idx = None;
let mut seen_varargs = false;
let mut seen_varkwargs = false;
let mut seen_pos_or_kw = false;
let mut seen_kw_only = false;
let mut pos_counter: usize = 0;
let mut slot_counter: usize = 0;
for (idx, field) in fields.iter_mut().enumerate() {
if seen_varkwargs {
return Err(syn::Error::new(
field.ident.span(),
"no fields may appear after a `#[from_args(varkwargs)]` field",
));
}
match field.kind {
FieldKind::PosOnly => {
if seen_pos_or_kw || seen_kw_only || seen_varargs {
return Err(syn::Error::new(
field.ident.span(),
"positional-only fields must come before positional-or-keyword, varargs, and keyword-only fields",
));
}
}
FieldKind::PosOrKeyword => {
if seen_varargs {
// Implicit kw_only after varargs.
field.kind = FieldKind::KwOnly;
seen_kw_only = true;
} else if seen_kw_only {
return Err(syn::Error::new(
field.ident.span(),
"positional-or-keyword fields cannot appear after keyword-only fields",
));
} else {
seen_pos_or_kw = true;
}View on GitHub (pinned to adc986b362)
Solutions
- Move the `#[from_args(pos_only)]` field to the top of the struct, before all positional-or-keyword, varargs, and keyword-only fields
- If the field does not need to be positional-only, remove the `#[from_args(pos_only)]` attribute so it becomes a normal positional-or-keyword field
- If the field was intended to be keyword-only, change the attribute to `#[from_args(kw_only)]` and keep it after the positional fields
Example fix
// before
#[derive(FromArgs)]
#[from_args(name = "f"])
struct FArgs {
x: i64,
#[from_args(pos_only)]
a: i64,
}
// after
#[derive(FromArgs)]
#[from_args(name = "f"])
struct FArgs {
#[from_args(pos_only)]
a: i64,
x: i64,
} Defensive patterns
Strategy: validation
Validate before calling
// Before compiling, check field order: all #[from_args(pos_only)] fields
// must be the first fields of the struct.
struct Fields<'a> { kinds: &'a [FieldKind] }
fn pos_only_first(kinds: &[&str]) -> bool {
let after_non_pos_only = kinds.iter().position(|k| *k != "pos_only");
match after_non_pos_only {
Some(i) => !kinds[i..].contains(&"pos_only"),
None => true,
}
} Prevention
- Declare pos_only fields at the top of every arg struct
- Mirror the target CPython function's parameter order when writing the struct
- Run cargo check after each field reorder
When it happens
Trigger: Deriving `FromArgs` on a struct where a field annotated with `#[from_args(pos_only)]` appears in the struct body after any plain (positional-or-keyword) field, any `#[from_args(varargs)]` field, or any `#[from_args(kw_only)]` field.
Common situations: Reordering struct fields while converting a hand-written `into_parts()` parser to `FromArgs`, or adding a new pos_only parameter to the end of an existing struct instead of the top.
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
- positional-or-keyword fields cannot appear after keyword-onl
- only one `#[from_args(varargs)]` field is allowed
- `varargs` cannot appear after keyword-only fields — Python h
- only one `#[from_args(varkwargs)]` field is allowed
- unknown style `{other}`; expected `def`, `clinic`, `c`, `c_n
AI-assisted analysis of pydantic/monty@adc986b362 (2026-09-13).
Data as JSON: /api/errors/437fdf75d629633b.
Report an issue: GitHub.