pola-rs/polars · error
StructArray must be initialized with DataType::Struct
Error message
StructArray must be initialized with DataType::Struct
What it means
StructArray::new_empty only accepts an ArrowDataType whose to_storage() is Struct(fields): it needs the field list to build one empty child array per field. Any other dtype panics because there is no field set to construct children from.
Source
Thrown at crates/polars-arrow/src/array/struct_/mod.rs:134
pub fn new(
dtype: ArrowDataType,
length: usize,
values: Vec<Box<dyn Array>>,
validity: Option<Bitmap>,
) -> Self {
Self::try_new(dtype, length, values, validity).unwrap()
}
/// Creates an empty [`StructArray`].
pub fn new_empty(dtype: ArrowDataType) -> Self {
if let ArrowDataType::Struct(fields) = &dtype.to_storage() {
let values = fields
.iter()
.map(|field| new_empty_array(field.dtype().clone()))
.collect();
Self::new(dtype, 0, values, None)
} else {
panic!("StructArray must be initialized with DataType::Struct");
}
}
/// Creates a null [`StructArray`] of length `length`.
pub fn new_null(dtype: ArrowDataType, length: usize) -> Self {
if let ArrowDataType::Struct(fields) = &dtype {
let values = fields
.iter()
.map(|field| new_null_array(field.dtype().clone(), length))
.collect();
Self::new(dtype, length, values, Some(Bitmap::new_zeroed(length)))
} else {
panic!("StructArray must be initialized with DataType::Struct");
}
}
}
// must useView on GitHub (pinned to 9b5d73fd00)
Solutions
- Use the generic dispatcher polars_arrow::array::new_empty_array(dtype) instead of calling StructArray::new_empty directly
- Match on matches!(dtype.to_storage(), ArrowDataType::Struct(_)) before calling and handle other variants explicitly
- Return a proper unsupported-dtype error for unexpected variants instead of reaching the panic
Example fix
// before let empty = StructArray::new_empty(dtype); // after let empty = polars_arrow::array::new_empty_array(dtype);
Defensive patterns
Strategy: type-guard
Validate before calling
fn struct_only(dtype: &ArrowDataType) -> Result<&ArrowDataType, String> {
match dtype.to_storage() {
ArrowDataType::Struct(_) => Ok(dtype),
other => Err(format!("expected Struct dtype, got {other:?}")),
}
} Type guard
fn is_struct_dtype(dtype: &ArrowDataType) -> bool {
matches!(dtype.to_storage(), ArrowDataType::Struct(_))
} Prevention
- Prefer polars_arrow::array::new_empty_array(dtype) over concrete constructors in generic code
- Handle every dtype variant explicitly in empty/null array factories
- Treat schema-driven dtypes as unvalidated input: match before dispatch
When it happens
Trigger: StructArray::new_empty(ArrowDataType::Null) or new_empty(List(..)) — usually reached from generic code that special-cases struct handling but falls through to the concrete constructor for non-struct dtypes.
Common situations: Schema evolution delivering a non-struct dtype where code assumed structs; matching on a logical/extension type whose storage is not Struct; copy-pasted empty-batch construction for heterogeneous schemas.
Related errors
- Union struct must be created with the corresponding Union Da
- MutableUtf8ValuesArray can only be initialized with DataType
- not implemented
- {:?} -> {:?} not supported
- FixedSizeListArray::arr_from_iter_with_dtype called with non
AI-assisted analysis of pola-rs/polars@9b5d73fd00 (2026-08-19).
Data as JSON: /api/errors/33810420fc4647c6.
Report an issue: GitHub.