{"record":{"id":"b57de7da9acbf456","repo":"databendlabs/databend","slug":"must-array-type","errorCode":null,"errorMessage":"must array type","messagePattern":"must array type","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/query/expression/src/types/array.rs","lineNumber":333,"sourceCode":"                len\n            )));\n        }\n\n        for i in 1..len {\n            if offsets[i] < offsets[i - 1] {\n                return Err(ErrorCode::Internal(format!(\n                    \"ArrayColumn offsets value must be equal or greater than previous value, but got {}\",\n                    offsets[i]\n                )));\n            }\n        }\n        Ok(())\n    }\n}\n\nimpl<T: ValueType> ArrayColumn<T> {\n    pub fn upcast(self, data_type: &DataType) -> ArrayColumn<AnyType> {\n        let values_type = data_type.as_array().expect(\"must array type\");\n        ArrayColumn {\n            values: T::upcast_column_with_type(self.values, values_type),\n            offsets: self.offsets,\n        }\n    }\n}\n\nimpl ArrayColumn<AnyType> {\n    pub fn try_downcast<T: AccessType>(&self) -> Result<ArrayColumn<T>> {\n        Ok(ArrayColumn {\n            values: T::try_downcast_column(&self.values)?,\n            offsets: self.offsets.clone(),\n        })\n    }\n}\n\npub struct ArrayIterator<'a, T: AccessType> {\n    values: &'a T::Column,","sourceCodeStart":315,"sourceCodeEnd":351,"githubUrl":"https://github.com/databendlabs/databend/blob/288d84d76e20a2f8f7173bda9691eb6ece301aa9/src/query/expression/src/types/array.rs#L315-L351","documentation":"ArrayColumn<T>::upcast converts a typed array column to ArrayColumn<AnyType>, and first extracts the inner element type via DataType::as_array(). The panic fires when the supplied data_type is not an array type (e.g. a scalar or struct type), which violates the caller's contract: upcast is only meaningful for columns whose logical type is Array.","triggerScenarios":"Calling upcast with a DataType that is not Array(..), e.g. passing the column's outer type when it is Nullable/Variant, or a type-mismatched metadata/type pairing in a cast or aggregation generic path.","commonSituations":"Generic expression code that upcasts array columns but receives metadata for a non-array type after nullable unwrapping mismatches; a function registered for arrays receiving scalar arguments due to a signature mix-up.","solutions":["Verify the DataType passed to upcast corresponds to the array column (it must be Array(inner_type)).","Unwrap Nullable before/consistently with how the column values were built.","Return a typed error instead of expect if the input type is externally supplied."],"exampleFix":"// before\nlet values_type = data_type.as_array().expect(\"must array type\");\n// after\nlet values_type = data_type.as_array().ok_or_else(|| ErrorCode::BadDataValueType(format!(\"expected array type, got {data_type}\")))?;","handlingStrategy":"type-guard","validationCode":"if data_type.as_array().is_none() {\n    return Err(ErrorCode::BadDataValueType(format!(\"expected array type, got {data_type}\")));\n}\nlet out = column.upcast(&data_type);","typeGuard":"fn is_array_type(dt: &DataType) -> bool { dt.as_array().is_some() }","tryCatchPattern":null,"preventionTips":["Keep column metadata and DataType unwrapping (remove_nullable) consistent.","Only call upcast on columns whose logical type is Array."],"tags":["panic","type-mismatch","array"],"backgroundTag":"type-mismatch","analyzedSha":"288d84d76e20a2f8f7173bda9691eb6ece301aa9","analyzedAt":"2026-09-11T11:29:36.208Z","contentChangedAt":"2026-09-11T11:29:36.208Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}