{"record":{"id":"06f71082255602dc","repo":"pydantic/monty","slug":"kwargs-not-supported-yet-cannot-be-combined-with-kwarg-error","errorCode":null,"errorMessage":"`kwargs_not_supported_yet` cannot be combined with `kwarg_error_name` — the override only applies to the unknown-kwarg dispatch path, which is skipped","messagePattern":"`kwargs_not_supported_yet` cannot be combined with `kwarg_error_name` — the override only applies to the unknown-kwarg dispatch path, which is skipped","errorType":"validation","errorClass":"syn::Error","httpStatus":null,"severity":"error","filePath":"crates/monty-macros/src/from_args.rs","lineNumber":275,"sourceCode":"\n        if self.kwarg_error_name.is_some() && !matches!(self.style, Style::Def | Style::Clinic | Style::Unpack) {\n            return err(\"`kwarg_error_name` is only meaningful with `style = def`, the default \\\n                 `clinic` style, or `style = unpack` (where it names the function in the \\\n                 `takes no keyword arguments` error) — the C families defer unknown-kwarg \\\n                 errors past binding\");\n        }\n\n        if self.kwargs_not_supported_yet {\n            if self.varkwargs_idx.is_some() {\n                return err(\"`kwargs_not_supported_yet` cannot be combined with `varkwargs` \\\n                     — the flag rejects every kwarg up front, so there's nothing to collect\");\n            }\n            if self.fields.iter().any(|f| matches!(f.kind, FieldKind::KwOnly)) {\n                return err(\"`kwargs_not_supported_yet` cannot be combined with `kw_only` fields \\\n                     — the flag rejects every kwarg up front, so kw_only slots are unreachable\");\n            }\n            if self.kwarg_error_name.is_some() {\n                return err(\"`kwargs_not_supported_yet` cannot be combined with `kwarg_error_name` \\\n                     — the override only applies to the unknown-kwarg dispatch path, which is skipped\");\n            }\n        }\n\n        // The runtime binder's fast path fills the first `n` positional slots\n        // and assumes that satisfies every required positional param — sound\n        // only if required positional fields precede defaulted ones (the same\n        // ordering Python enforces for `def` signatures).\n        let mut seen_positional_default = false;\n        for field in &self.fields {\n            if !matches!(field.kind, FieldKind::PosOnly | FieldKind::PosOrKeyword) {\n                continue;\n            }\n            if field.default.is_some() {\n                seen_positional_default = true;\n            } else if seen_positional_default {\n                return Err(syn::Error::new(\n                    field.ident.span(),","sourceCodeStart":257,"sourceCodeEnd":293,"githubUrl":"https://github.com/pydantic/monty/blob/adc986b362e3961f407868cb118a99fe831b9e61/crates/monty-macros/src/from_args.rs#L257-L293","documentation":"This is a compile-time validation error from monty's `#[derive(FromArgs)]` proc macro (in `crates/monty-macros/src/from_args.rs:275`, inside `validate`). A struct declared `kwargs_not_supported_yet` also set `kwarg_error_name`. The flag makes the binder reject every keyword argument up front, which skips the unknown-kwarg dispatch path entirely — so the custom function-name override in `kwarg_error_name` would never be used, and the macro refuses the contradictory combination instead of silently ignoring it.","triggerScenarios":"Writing `#[from_args(name = \"f\", kwargs_not_supported_yet, kwarg_error_name = \"f\")]` (any `kwarg_error_name` value) on a `#[derive(FromArgs)]` struct. It is a compile error at the derive site, not a runtime failure.","commonSituations":"A developer porting a CPython `PyArg_UnpackTuple`-style function wants the exact `f() takes no keyword arguments` message (via `kwarg_error_name`) and also adds `kwargs_not_supported_yet` to reject kwargs eagerly, not realizing the two annotations target different code paths and cannot coexist.","solutions":["Remove `kwarg_error_name` — `kwargs_not_supported_yet` already rejects all kwargs; the default error message is used.","Remove `kwargs_not_supported_yet` if you need the custom `takes no keyword arguments` message with the function name; keep `style = unpack` so the unknown-kwarg dispatch path runs and `kwarg_error_name` applies.","Check `crates/monty-macros/README.md` for which attributes are mutually exclusive and pick the single annotation matching the CPython parser family you are modeling."],"exampleFix":"// before\n#[derive(FromArgs)]\n#[from_args(name = \"normalize\", style = unpack, kwargs_not_supported_yet, kwarg_error_name = \"normalize\")]\nstruct NormalizeArgs {\n    #[from_args(pos_only)]\n    form: StrArg,\n}\n\n// after — keep the custom message, drop the eager flag\n#[derive(FromArgs)]\n#[from_args(name = \"normalize\", style = unpack, kwarg_error_name = \"normalize\")]\nstruct NormalizeArgs {\n    #[from_args(pos_only)]\n    form: StrArg,\n}","handlingStrategy":"validation","validationCode":"// Before relying on both attributes, grep the derive input — the macro rejects:\n// attrs contains 'kwargs_not_supported_yet' AND attrs contains 'kwarg_error_name'\nconst conflicting = attrs.includes('kwargs_not_supported_yet') && attrs.includes('kwarg_error_name');\nif (conflicting) throw new Error('pick one: eager kwarg rejection or custom kwarg error name');","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Read crates/monty-macros/README.md's attribute compatibility table before combining from_args attributes.","When a compile error appears, trust its explanation — it documents exactly which code path makes the combination unsound.","Keep one annotation per concern: eager rejection OR custom message, never both."],"tags":["rust","proc-macro","compile-time","argument-parsing","conflicting-options"],"backgroundTag":"conflicting-config-options","analyzedSha":"adc986b362e3961f407868cb118a99fe831b9e61","analyzedAt":"2026-09-13T19:19:18.698Z","contentChangedAt":"2026-09-13T19:19:18.698Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}