{"record":{"id":"2145b99d8262411c","repo":"databendlabs/databend","slug":"datatype-map-should-contain-a-struct-field-child","errorCode":null,"errorMessage":"DataType::Map should contain a struct field child","messagePattern":"DataType::Map should contain a struct field child","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/query/storages/delta/src/arrow56_conversion.rs","lineNumber":310,"sourceCode":"            .into()),\n            ArrowDataType::LargeListView(field) => Ok(ArrayType::new(\n                (*field).data_type().try_into_value()?,\n                (*field).is_nullable(),\n            )\n            .into()),\n            ArrowDataType::FixedSizeList(field, _) => Ok(ArrayType::new(\n                (*field).data_type().try_into_value()?,\n                (*field).is_nullable(),\n            )\n            .into()),\n            ArrowDataType::Map(field, _) => {\n                if let ArrowDataType::Struct(struct_fields) = field.data_type() {\n                    let key_type = DataType::try_from_value(struct_fields[0].data_type())?;\n                    let value_type = DataType::try_from_value(struct_fields[1].data_type())?;\n                    let value_type_nullable = struct_fields[1].is_nullable();\n                    Ok(MapType::new(key_type, value_type, value_type_nullable).into())\n                } else {\n                    panic!(\"DataType::Map should contain a struct field child\");\n                }\n            }\n            // Dictionary types are just an optimized in-memory representation of an array.\n            // Schema-wise, they are the same as the value type.\n            ArrowDataType::Dictionary(_, value_type) => Ok(value_type.as_ref().try_into_value()?),\n            s => Err(Arrow56ConversionError::InvalidDataType(format!(\n                \"Invalid data type for Delta Lake: {s}\"\n            ))),\n        }\n    }\n}\n","sourceCodeStart":292,"sourceCodeEnd":322,"githubUrl":"https://github.com/databendlabs/databend/blob/288d84d76e20a2f8f7173bda9691eb6ece301aa9/src/query/storages/delta/src/arrow56_conversion.rs#L292-L322","documentation":"This is an internal invariant panic in the Delta Lake storage's Arrow 5.6 type conversion layer. When converting an Arrow Map type to Databend's DataType, the converter expects the Map's single field child to be a Struct containing exactly the key and value fields; any Arrow schema that violates this (e.g. a Map whose child is not a Struct) triggers an immediate panic via unreachable!() instead of a recoverable error.","triggerScenarios":"Calling DataType::try_from_value on an Arrow Field whose data_type is ArrowDataType::Map when field.data_type() does not match ArrowDataType::Struct(_) — e.g. reading a Delta table whose Parquet/Arrow schema encodes Map with a malformed or non-struct child field.","commonSituations":"Ingesting a Delta table written by another engine or library version that serializes Map columns differently; corrupted or hand-crafted Parquet metadata; a version mismatch between the arrow crate that wrote the data and the arrow56 shim used by the converter.","solutions":["Inspect the offending Arrow schema and confirm the Map field's child is a Struct with key and value entries","Fix the upstream writer or regenerate the Delta table so Map columns use the standard struct(key, value) child layout","Replace the panic with a proper Err(Arrow56ConversionError::InvalidDataType(...)) so bad schemas surface as a readable error instead of aborting the query","Pin/align the arrow crate versions used to write and read the data"],"exampleFix":"// before\n} else {\n    panic!(\"DataType::Map should contain a struct field child\");\n}\n// after\n} else {\n    return Err(Arrow56ConversionError::InvalidDataType(format!(\n        \"DataType::Map should contain a struct field child, got {:?}\",\n        field.data_type()\n    )));\n}","handlingStrategy":"validation","validationCode":"fn is_valid_arrow_map(field: &ArrowField) -> bool {\n    matches!(field.data_type(), ArrowDataType::Struct(children) if children.len() >= 2)\n}\nif !is_valid_arrow_map(&field) {\n    return Err(Arrow56ConversionError::InvalidDataType(\n        \"Map field child is not a struct\".into(),\n    ));\n}","typeGuard":"fn is_struct_type(dt: &ArrowDataType) -> bool {\n    matches!(dt, ArrowDataType::Struct(_))\n}","tryCatchPattern":"// Panics cannot be caught idiomatically in Rust; prefer validating before conversion.\nlet result = std::panic::catch_unwind(|| DataType::try_from_value(&field));\nmatch result {\n    Ok(Ok(dt)) => use_datatype(dt),\n    Ok(Err(e)) => report_conversion_error(e),\n    Err(_) => report_schema_bug(),\n}","preventionTips":["Validate Arrow schemas coming from external Delta/Parquet sources before conversion","Keep arrow crate versions aligned between writer and reader paths","Prefer returning Err over panic! for malformed external input"],"tags":["arrow","delta-lake","schema","panic"],"backgroundTag":"internal-invariant-violation","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"}