pydantic/monty · error · syn::Error

`kwargs_not_supported_yet` cannot be combined with `varkwarg

Error message

`kwargs_not_supported_yet` cannot be combined with `varkwargs` — the flag rejects every kwarg up front, so there's nothing to collect

What it means

A `#[derive(FromArgs)]` struct sets `kwargs_not_supported_yet` while also declaring a `varkwargs` (`**kwargs`) field. The flag makes the generated parser reject every keyword argument up front, so there would be no kwargs left to collect into the field — the two declarations contradict each other and are rejected at compile time.

Source

Thrown at crates/monty-macros/src/from_args.rs:267

                     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 {
            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 {

View on GitHub (pinned to adc986b362)

Solutions

  1. Remove the `varkwargs` field if kwargs should be rejected.
  2. Remove `kwargs_not_supported_yet` if the function genuinely accepts `**kwargs`; add kwarg support to the binder instead of using the escape-hatch flag.

Example fix

// before
#[derive(FromArgs)]
#[from_args(kwargs_not_supported_yet)]
struct Args { a: Value, #[from_args(varkwargs)] kw: Vec<(String, Value)> }

// after
#[derive(FromArgs)]
#[from_args(kwargs_not_supported_yet)]
struct Args { a: Value }
Defensive patterns

Strategy: validation

Validate before calling

fn kwargs_flag_conflicts(kwargs_not_supported_yet: bool, has_varkwargs: bool) -> bool {
    kwargs_not_supported_yet && has_varkwargs
}

Prevention

When it happens

Trigger: Compiling `#[derive(FromArgs)] #[from_args(kwargs_not_supported_yet)] struct Args { a: i64, #[from_args(varkwargs)] kw: Vec<(String, Value)> }`. Checked in `Signature::validate` (crates/monty-macros/src/from_args.rs:265-269).

Common situations: Adding `kwargs_not_supported_yet` as a temporary measure to a struct that already collects kwargs; merging two structs — one that rejects kwargs, one that collects them — without pruning attributes.

Related errors


AI-assisted analysis of pydantic/monty@adc986b362 (2026-09-13). Data as JSON: /api/errors/691ff2351dfd5778. Report an issue: GitHub.