{"record":{"id":"4b636fe64717e24d","repo":"pola-rs/polars","slug":"unique-operation-not-supported-for-dtype","errorCode":null,"errorMessage":"`unique` operation not supported for dtype `{}`","messagePattern":"`unique` operation not supported for dtype `(.+?)`","errorType":"panic","errorClass":"PolarsError::InvalidOperation","httpStatus":null,"severity":"error","filePath":"crates/polars-core/src/frame/group_by/aggregations/dispatch.rs","lineNumber":289,"sourceCode":"                            return None;\n                        }\n                        let v = mask.sliced_unchecked(first as usize, len as usize);\n                        let tz = v.trailing_zeros() as IdxSize;\n                        if tz == len { None } else { Some(len - tz - 1) }\n                    })\n                    .collect_ca(PlSmallStr::EMPTY)\n            },\n        };\n\n        out.into_series()\n    }\n\n    #[doc(hidden)]\n    pub unsafe fn agg_n_unique(&self, groups: &GroupsType) -> Series {\n        let values = self.to_physical_repr();\n        let dtype = values.dtype();\n        let values = if dtype.contains_objects() {\n            panic!(\"{}\", polars_err!(opq = unique, dtype));\n        } else if let Some(ca) = values.try_str() {\n            ca.as_binary().into_column()\n        } else if dtype.is_nested() {\n            encode_rows_unordered(&[values.into_owned().into_column()])\n                .unwrap()\n                .into_column()\n        } else {\n            values.into_owned().into_column()\n        };\n\n        // Keep the Column for the sort-fallback path. Big groups go through\n        // `Series::n_unique`, bypassing the amortized hashset.\n        let col = values.clone();\n        let values = values.rechunk_to_arrow(CompatLevel::newest());\n        let values = values.as_ref();\n        let state = amortized_unique_from_dtype(values.dtype());\n\n        struct CloneWrapper(Box<dyn AmortizedUnique>);","sourceCodeStart":271,"sourceCodeEnd":307,"githubUrl":"https://github.com/pola-rs/polars/blob/68506541d2de983056c9eb244e1ea05fab377dfc/crates/polars-core/src/frame/group_by/aggregations/dispatch.rs#L271-L307","documentation":"agg_n_unique is the group_by aggregation behind n_unique()/approx_n_unique style operations. Before counting distinct values it takes the physical representation; if that representation contains objects (DataType::Object, arbitrary Rust T: PolarsObject values), it panics because hashing/arbitrary object equality is not supported on this path.","triggerScenarios":"A group_by aggregation that needs unique counts over a column whose dtype is Object, e.g. df.group_by([\"k\"]).agg(pl.col(\"obj\").n_unique()) in Python where \"obj\" holds Python objects, or the Rust equivalent with a PolarsObject column.","commonSituations":"polars-python users who created object columns (e.g. via pl.Series with mixed Python objects, or UDFs returning objects); Rust users with custom PolarsObject types; Arrow extension-type data imported as Object.","solutions":["Cast or serialize the object column to Utf8/Binary before the aggregation: pl.col(\"obj\").cast(pl.String).n_unique()","Replace the object column with a supported dtype (struct, list, enum/categorical) at ingestion time","Drop the object column from the n_unique aggregation and compute uniqueness on a typed key instead"],"exampleFix":"# before\ndf.group_by(\"k\").agg(pl.col(\"obj\").n_unique())\n\n# after\ndf.group_by(\"k\").agg(pl.col(\"obj\").cast(pl.String).n_unique())","handlingStrategy":"validation","validationCode":"fn is_object_col(s: &Series) -> bool {\n    s.dtype().contains_objects()\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Check dtype().contains_objects() before n_unique aggregations","Avoid creating Object columns; map external objects to String/Binary/Struct at ingestion","In Python, avoid object-dtype Series (mixed Python types); inspect pl.Series.dtype before grouping"],"tags":["polars","dtype","object-dtype","n-unique","group-by","panic"],"backgroundTag":"unsupported-dtype-for-operation","analyzedSha":"68506541d2de983056c9eb244e1ea05fab377dfc","analyzedAt":"2026-08-19T12:15:06.350Z","contentChangedAt":"2026-08-19T12:15:06.350Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}