pydantic/monty · error · syn::Error
`kwargs_not_supported_yet` cannot be combined with…
Error message
`kwargs_not_supported_yet` cannot be combined with `kw_only` fields — the flag rejects every kwarg up front, so kw_only slots are unreachable
What it means
A `#[derive(FromArgs)]` struct sets `kwargs_not_supported_yet` while declaring one or more `kw_only` fields. The flag rejects every keyword argument up front, making any keyword-only slot permanently unreachable — no caller could ever satisfy it. The macro rejects this dead-code configuration at compile time.
Solutions
- Remove `kwargs_not_supported_yet` — its purpose (a temporary stand-in until kwarg support exists) conflicts with having kw_only fields.
- If kwargs must still be rejected, drop the `kw_only` field(s) and express the parameter as positional instead.
- If a custom rejection message is wanted for other kwargs, `kwarg_error_name` may fit; note the separate error that it also cannot combine with this flag.
Example fix
// before
#[derive(FromArgs)]
#[from_args(kwargs_not_supported_yet)]
struct Args { #[from_args(kw_only)] key: Value }
// after
#[derive(FromArgs)]
struct Args { #[from_args(kw_only)] key: Value } Defensive patterns
Strategy: validation
Validate before calling
fn kw_only_unreachable(kwargs_not_supported_yet: bool, has_kw_only: bool) -> bool {
kwargs_not_supported_yet && has_kw_only
} Prevention
- Any kw_only field implies kwargs are supported — the rejection flag must be gone by then.
- Review #[from_args(...)] flags whenever adding a kw_only field to an existing struct.
When it happens
Trigger: Compiling `#[derive(FromArgs)] #[from_args(kwargs_not_supported_yet)] struct Args { #[from_args(kw_only)] key: Value }`. Checked in `Signature::validate` (crates/monty-macros/src/from_args.rs:270-273).
Common situations: Marking a struct's parameters `kw_only` to match a Python signature while the flag (added earlier as a TODO marker) is still present; forgetting to remove the flag once kwarg support lands.
Related errors
- `at_most_total` cannot be combined with `style = def` or…
- `at_most_total` cannot be combined with `varargs` or…
- `bad_arg`/`bad_arg_named` cannot be combined with `style =…
- `kwarg_error_name` is only meaningful with `style = def`…
- `kwargs_not_supported_yet` cannot be combined with…
AI-assisted analysis of pydantic/monty@adc986b362 (2026-09-13).
Data as JSON: /api/errors/0f61ca2e2c4debad.
Report an issue: GitHub.
Appendix: source
Thrown at crates/monty-macros/src/from_args.rs:271
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 {
if self.varkwargs_idx.is_some() {
return err("`kwargs_not_supported_yet` cannot be combined with `varkwargs` \
— the flag rejects every kwarg up front, so there's nothing to collect");
}
if self.fields.iter().any(|f| matches!(f.kind, FieldKind::KwOnly)) {
return err("`kwargs_not_supported_yet` cannot be combined with `kw_only` fields \
— the flag rejects every kwarg up front, so kw_only slots are unreachable");
}
if self.kwarg_error_name.is_some() {
return err("`kwargs_not_supported_yet` cannot be combined with `kwarg_error_name` \
— the override only applies to the unknown-kwarg dispatch path, which is skipped");
}
}
// The runtime binder's fast path fills the first `n` positional slots
// and assumes that satisfies every required positional param — sound
// only if required positional fields precede defaulted ones (the same
// ordering Python enforces for `def` signatures).
let mut seen_positional_default = false;
for field in &self.fields {
if !matches!(field.kind, FieldKind::PosOnly | FieldKind::PosOrKeyword) {
continue;
}
if field.default.is_some() {View on GitHub (pinned to adc986b362)