{"record":{"id":"3b29879401314294","repo":"pola-rs/polars","slug":"validity-must-be-equal-to-the-array-s-length-3b2987","errorCode":null,"errorMessage":"validity must be equal to the array's length","messagePattern":"validity must be equal to the array's length","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/polars-arrow/src/array/mod.rs","lineNumber":508,"sourceCode":"macro_rules! impl_mut_validity {\n    () => {\n        /// Returns this array with a new validity.\n        /// # Panic\n        /// Panics iff `validity.len() != self.len()`.\n        #[must_use]\n        #[inline]\n        pub fn with_validity(mut self, validity: Option<Bitmap>) -> Self {\n            self.set_validity(validity);\n            self\n        }\n\n        /// Sets the validity of this array.\n        /// # Panics\n        /// This function panics iff `values.len() != self.len()`.\n        #[inline]\n        pub fn set_validity(&mut self, validity: Option<Bitmap>) {\n            if matches!(&validity, Some(bitmap) if bitmap.len() != self.len()) {\n                panic!(\"validity must be equal to the array's length\")\n            }\n            self.validity = validity;\n        }\n\n        /// Takes the validity of this array, leaving it without a validity mask.\n        #[inline]\n        pub fn take_validity(&mut self) -> Option<Bitmap> {\n            self.validity.take()\n        }\n    }\n}\n\n// macro implementing `with_validity`, `set_validity` and `apply_validity` for mutable arrays\nmacro_rules! impl_mutable_array_mut_validity {\n    () => {\n        /// Returns this array with a new validity.\n        /// # Panic\n        /// Panics iff `validity.len() != self.len()`.","sourceCodeStart":490,"sourceCodeEnd":526,"githubUrl":"https://github.com/pola-rs/polars/blob/68506541d2de983056c9eb244e1ea05fab377dfc/crates/polars-arrow/src/array/mod.rs#L490-L526","documentation":"Compile-time panic from #[polars_expr] in pyo3-polars-derive (lib.rs:123). The macro dispatches code generation purely on the NAMES of the function's parameters after the first: the only recognized names are \"kwargs\" and \"context\". With exactly one extra parameter, any name other than those two panics with \"didn't expect argument {a}\", where {a} is the offending parameter name. The first parameter (the &[Series] input slice) is skipped, so its name is free.","triggerScenarios":"A two-parameter function whose second parameter is misspelled or renamed: fn f(input: &[Series], kw_args: MyKwargs), fn f(input: &[Series], ctx: CallerContext), fn f(input: &[Series], options: MyKwargs). Also fires when the first parameter is actually a receiver, e.g. fn f(&self, inputs: &[Series]): skip(1) drops &self and \"inputs\" is then reported as the unexpected argument name.","commonSituations":"IDE rename refactoring that renames kwargs to kw_args or context to ctx; copying a signature from a non-plugin function; style-driven renaming of parameters without knowing the names are load-bearing for the macro; porting plugins between pyo3-polars versions where conventions changed.","solutions":["Rename the second parameter to exactly kwargs (type: your Deserialize kwargs struct) or exactly context (type: CallerContext from pyo3_polars::derive)","If the extra parameter is not needed, delete it so the function is only fn f(inputs: &[Series]) -> PolarsResult<Series>","If the reported name is \"inputs\", your first parameter is not the inputs slice (often a leftover &self): remove the receiver so inputs: &[Series] is first","Re-run cargo check to confirm the macro accepts the signature"],"exampleFix":"// before — parameter must be named exactly `kwargs`\n#[polars_expr(output_type=String)]\nfn append_kw(input: &[Series], kw_args: MyKwargs) -> PolarsResult<Series> {\n    todo!()\n}\n\n// after\n#[polars_expr(output_type=String)]\nfn append_kw(input: &[Series], kwargs: MyKwargs) -> PolarsResult<Series> {\n    todo!()\n}","handlingStrategy":"validation","validationCode":"# ci/check_polars_expr.py — run before cargo build\nimport re, sys, pathlib\npat = re.compile(r\"#\\[polars_expr\\([^)]*\\)\\]\\s*(?:pub\\s+)?fn\\s+\\w+\\(([^)]*)\\)\", re.S)\nallowed = ([], [\"kwargs\"], [\"context\"], [\"context\", \"kwargs\"])\nfor f in pathlib.Path(\"src\").rglob(\"*.rs\"):\n    for m in pat.finditer(f.read_text()):\n        params = [p.strip() for p in m.group(1).split(\",\") if p.strip()]\n        names = [p.split(\":\")[0].strip() for p in params[1:]]\n        if names not in allowed:\n            sys.exit(f\"{f}: extra params {names} must be [], ['kwargs'], ['context'] or ['context','kwargs'])\")","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Treat parameter names kwargs and context as part of the public API of the macro — never rename them","Exclude plugin function parameters from IDE-wide rename refactorings","Let the compiler check early: run cargo check after every signature edit in the plugin crate"],"tags":["rust","proc-macro","polars","compile-time","parameter-names"],"backgroundTag":"proc-macro-panicked","analyzedSha":"68506541d2de983056c9eb244e1ea05fab377dfc","analyzedAt":"2026-08-19T12:15:06.350Z","contentChangedAt":"2026-08-19T12:15:06.350Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}