pydantic/monty · error · syn::Error

keyword-only fields must have a `default` — the runtime bind

Error message

keyword-only fields must have a `default` — the runtime binder's fast paths skip the aggregated missing-keyword check, so a required keyword-only parameter would report the wrong error; extend the binder before allowing this

What it means

A compile-time validation error from the `FromArgs` derive: every keyword-only field (`#[from_args(kw_only)]`) must carry a `default`. The runtime binder's fast paths return before any aggregated missing-keyword check, so a required keyword-only parameter would surface as the wrong error (typically a generic missing-argument error).

Source

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

            && !is_vec_of_value(&self.fields[idx].ty)
        {
            return Err(syn::Error::new(
                self.fields[idx].ident.span(),
                "`varargs` fields must be `Vec<Value>` — coerce elements in the function body",
            ));
        }

        // The runtime binder's fast paths return before the aggregated
        // missing-keyword check runs, so a required kw_only slot could slip
        // through binding unfilled and later surface `Bound::require`'s
        // positional wording. No current signature needs one; reject until
        // the fast paths learn to check for them.
        if let Some(field) = self
            .fields
            .iter()
            .find(|f| matches!(f.kind, FieldKind::KwOnly) && f.default.is_none())
        {
            return Err(syn::Error::new(
                field.ident.span(),
                "keyword-only fields must have a `default` — the runtime binder's fast \
                 paths skip the aggregated missing-keyword check, so a required \
                 keyword-only parameter would report the wrong error; extend the binder \
                 before allowing this",
            ));
        }

        // `default` / `static_string` describe a named parameter slot; on the
        // collector fields they would be silently dead configuration.
        for idx in [self.varargs_idx, self.varkwargs_idx].into_iter().flatten() {
            let field = &self.fields[idx];
            if field.default.is_some() || field.static_string.is_some() {
                return Err(syn::Error::new(
                    field.ident.span(),
                    "`default` and `static_string` cannot be applied to `varargs` / \
                     `varkwargs` fields — they configure a named parameter slot, which \
                     collector fields don't own",

View on GitHub (pinned to adc986b362)

Solutions

  1. Add a `default` to the kw-only field and validate emptiness in the body if 'required' semantics are needed
  2. Make the field positional-or-keyword (required positionals are supported) if call-shape allows
  3. Extend the runtime binder's fast paths with an aggregated missing-keyword check before lifting this restriction

Example fix

// before
#[derive(FromArgs)]
struct OpenArgs {
    path: String,
    #[from_args(kw_only)]
    encoding: String, // required kw-only — rejected
}
// after
#[derive(FromArgs)]
struct OpenArgs {
    path: String,
    #[from_args(kw_only, default)]
    encoding: Option<String>, // enforce requirement in the body if needed
}
Defensive patterns

Strategy: validation

Validate before calling

// every kw_only field needs a default
#[from_args(kw_only, default)] encoding: Option<String>

Prevention

When it happens

Trigger: Declaring a field with `#[from_args(kw_only)]` and no `#[from_args(default = ...)]`, e.g. a required `encoding: String` marked kw_only.

Common situations: Porting a CPython function with a required keyword-only parameter (like `open(..., encoding)`); assuming the macro supports required kw-only params because Python does.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


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