pydantic/monty · error · syn::Error

ToArgs does not yet support `varkwargs` fields

Error message

ToArgs does not yet support `varkwargs` fields

What it means

A compile-time error from the `ToArgs` derive macro, emitted as a `to_compile_error!` token stream for the specific field. A field tagged `#[from_args(varkwargs)]` cannot be serialized back into call arguments by `ToArgs` — the feature is not implemented, and the macro rejects it at codegen rather than silently omitting the field from the emitted arguments.

Source

Thrown at crates/monty-macros/src/to_args.rs:98

        }
    });

    let kw_pushes = proj_fields.iter().map(|f| {
        let ident = &f.ident;
        let ty = &f.ty;
        let name_lit = LitStr::new(&ident.to_string(), ident.span());
        match f.kind {
            FieldKind::KwOnly => quote! {
                __kw.push((
                    crate::MontyObject::String(#name_lit.to_owned()),
                    <#ty as crate::args::ToMontyObject>::into_monty_object(self.#ident),
                ));
            },
            FieldKind::Varkwargs => {
                // No caller needs this yet; reject at codegen rather than
                // silently dropping the field.
                let span = ident.span();
                let err = syn::Error::new(span, "ToArgs does not yet support `varkwargs` fields").to_compile_error();
                quote! { #err }
            }
            _ => quote! {},
        }
    });

    Ok(quote! {
        #[automatically_derived]
        impl crate::args::ToArgs for #struct_ident {
            fn to_args(
                self,
            ) -> (
                ::std::vec::Vec<crate::MontyObject>,
                ::std::vec::Vec<(crate::MontyObject, crate::MontyObject)>,
            ) {
                let mut __pos: ::std::vec::Vec<crate::MontyObject> = ::std::vec::Vec::new();
                let mut __kw: ::std::vec::Vec<(crate::MontyObject, crate::MontyObject)> =
                    ::std::vec::Vec::new();

View on GitHub (pinned to adc986b362)

Solutions

  1. Remove the `#[from_args(varkwargs)]` field from the struct given to `ToArgs`, keeping it only on the `FromArgs` side (split into two structs if needed)
  2. Represent the keyword arguments as individual `#[from_args(kw_only)]` fields, which `ToArgs` supports
  3. If round-tripping kwargs is genuinely needed, hand-write the conversion instead of deriving

Example fix

// before
#[derive(ToArgs)]
struct CallArgs {
    x: i64,
    #[from_args(varkwargs)]
    kwargs: Value,
}

// after
#[derive(ToArgs)]
struct CallArgs {
    x: i64,
}
Defensive patterns

Strategy: validation

Validate before calling

// ToArgs rejects varkwargs fields — keep them off structs passed to ToArgs.
fn to_args_compatible(kinds: &[&str]) -> bool {
    !kinds.contains(&"varkwargs")
}

Prevention

When it happens

Trigger: Deriving `ToArgs` on a struct that has a field annotated `#[from_args(varkwargs)]`.

Common situations: Sharing one struct definition between the inbound (`FromArgs`) and outbound (`ToArgs`) directions of a call, where the inbound side supports varkwargs but the outbound side does not.

Related errors


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