{"record":{"id":"8c9a0518d5428018","repo":"pola-rs/polars","slug":"non-categorical-enum-dtype-in-categoricalchunkedbu","errorCode":null,"errorMessage":"non-Categorical/Enum dtype in CategoricalChunkedbuilder","messagePattern":"non-Categorical/Enum dtype in CategoricalChunkedbuilder","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/polars-core/src/chunked_array/builder/categorical.rs","lineNumber":17,"sourceCode":"use arrow::bitmap::BitmapBuilder;\n\nuse crate::prelude::*;\n\npub struct CategoricalChunkedBuilder<T: PolarsCategoricalType> {\n    name: PlSmallStr,\n    dtype: DataType,\n    mapping: Arc<CategoricalMapping>,\n    is_enum: bool,\n    cats: Vec<T::Native>,\n    validity: BitmapBuilder,\n}\n\nimpl<T: PolarsCategoricalType> CategoricalChunkedBuilder<T> {\n    pub fn new(name: PlSmallStr, dtype: DataType) -> Self {\n        let (DataType::Categorical(_, mapping) | DataType::Enum(_, mapping)) = &dtype else {\n            panic!(\"non-Categorical/Enum dtype in CategoricalChunkedbuilder\")\n        };\n        Self {\n            name,\n            mapping: mapping.clone(),\n            is_enum: matches!(dtype, DataType::Enum(_, _)),\n            dtype,\n            cats: Vec::new(),\n            validity: BitmapBuilder::new(),\n        }\n    }\n\n    pub fn dtype(&self) -> &DataType {\n        &self.dtype\n    }\n\n    pub fn reserve(&mut self, len: usize) {\n        self.cats.reserve(len);\n        self.validity.reserve(len);","sourceCodeStart":1,"sourceCodeEnd":35,"githubUrl":"https://github.com/pola-rs/polars/blob/9b5d73fd00236295624374b075d16b1fe6ec6df9/crates/polars-core/src/chunked_array/builder/categorical.rs#L1-L35","documentation":"CategoricalChunkedBuilder::new(name, dtype) destructures its dtype argument as DataType::Categorical(_, mapping) or DataType::Enum(_, mapping); any other dtype panics immediately with 'non-Categorical/Enum dtype in CategoricalChunkedbuilder'. This is an internal precondition: the builder must be constructed with the exact categorical dtype it will emit, including the categories mapping.","triggerScenarios":"Constructing CategoricalChunkedBuilder in Rust with a non-categorical dtype (DataType::String, UInt32, or a Categorical variant from an older polars version without the mapping field); passing a dtype derived from schema inference or a plain Field instead of cloning the source categorical column's dtype.","commonSituations":"Refactors that rebuild the dtype from a schema rather than cloning the source column's dtype; upgrades across polars versions where Enum and per-column mappings were introduced, leaving stale dtype constructors; copy-pasted builder code where the dtype argument drifted from the data.","solutions":["Pass the dtype of the categorical being consumed: source.dtype().clone() instead of a reconstructed DataType","Validate before constructing: matches!(dtype, DataType::Categorical(_, _) | DataType::Enum(_, _))","Prefer higher-level APIs (CategoricalChunked::from_iter, categorical union helpers) that construct the builder with the correct dtype for you"],"exampleFix":"// before\nlet b = CategoricalChunkedBuilder::<CategoricalIdxType>::new(name, DataType::String); // panics\n// after\nlet dtype = DataType::Categorical(None, mapping.clone()); // or source.dtype().clone()\nlet b = CategoricalChunkedBuilder::<CategoricalIdxType>::new(name, dtype);","handlingStrategy":"type-guard","validationCode":"// Rust: validate before constructing the builder\nassert!(\n    matches!(dtype, DataType::Categorical(_, _) | DataType::Enum(_, _)),\n    \"CategoricalChunkedBuilder requires a Categorical/Enum dtype, got {dtype}\"\n);","typeGuard":"fn is_categorical_dtype(dtype: &DataType) -> bool {\n    matches!(dtype, DataType::Categorical(_, _) | DataType::Enum(_, _))\n}","tryCatchPattern":null,"preventionTips":["Clone the source column's dtype instead of reconstructing DataType by hand","Keep builder construction behind wrapper functions that own the dtype invariant","After polars upgrades, grep for DataType::Categorical constructors to confirm the mapping argument is still provided"],"tags":["polars","categorical","dtype","builder","panic","precondition"],"backgroundTag":"invalid-dtype-argument","analyzedSha":"9b5d73fd00236295624374b075d16b1fe6ec6df9","analyzedAt":"2026-08-19T12:15:06.350Z","contentChangedAt":"2026-08-19T12:15:06.350Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}