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

  1. Remove `kwargs_not_supported_yet` — its purpose (a temporary stand-in until kwarg support exists) conflicts with having kw_only fields.
  2. If kwargs must still be rejected, drop the `kw_only` field(s) and express the parameter as positional instead.
  3. 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

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


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)