{"record":{"id":"f6714108a2ddbf59","repo":"dbt-labs/dbt-core","slug":"expected-field-should-be-struct","errorCode":null,"errorMessage":"expected_field should be Struct","messagePattern":"expected_field should be Struct","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/dbt-tracing/src/serialize/arrow.rs","lineNumber":860,"sourceCode":"\nfn normalize_struct_column(\n    path: &str,\n    array: &ArrayRef,\n    expected_field: &Field,\n    actual_field: &Field,\n) -> Result<NormalizedColumn, Vec<String>> {\n    let struct_array = array\n        .as_any()\n        .downcast_ref::<StructArray>()\n        .ok_or_else(|| {\n            vec![format!(\n                \"field {path}: expected Struct but found {:?}\",\n                array.data_type()\n            )]\n        })?;\n\n    let DataType::Struct(expected_fields) = expected_field.data_type() else {\n        unreachable!(\"expected_field should be Struct\");\n    };\n\n    let DataType::Struct(actual_fields) = actual_field.data_type() else {\n        return Err(vec![format!(\n            \"field {path}: expected Struct but found {:?}\",\n            actual_field.data_type()\n        )]);\n    };\n\n    let mut child_arrays = Vec::with_capacity(expected_fields.len());\n    let mut child_fields = Vec::with_capacity(expected_fields.len());\n    let mut errors = Vec::new();\n    let mut needs_rebuild = false;\n\n    for expected_child in expected_fields.iter() {\n        let child_path = format!(\"{path}.{}\", expected_child.name());\n        let Some((child_index, actual_child_field)) = actual_fields\n            .iter()","sourceCodeStart":842,"sourceCodeEnd":878,"githubUrl":"https://github.com/dbt-labs/dbt-core/blob/0267ce9170576975b76b64ce856b2e5848e96617/crates/dbt-tracing/src/serialize/arrow.rs#L842-L878","documentation":"Arrow schema normalization invariant panic in dbt-tracing. normalize_struct_column is only invoked after both the expected and actual fields were verified to be DataType::Struct (the actual check returns an Err above); if the expected field is not Struct at this point, the caller's dispatch logic is wrong. The panic signals a bug in the recursive column-normalization dispatch rather than bad user input.","triggerScenarios":"normalize_column dispatching to normalize_struct_column with an expected_field whose data_type is not DataType::Struct.","commonSituations":"Schema evolution in the trace parquet format; hand-edited or older trace files whose schema diverges from the code's expectations; bugs introduced when adding new nested column types.","solutions":["Ensure trace files were produced by a compatible dbt-tracing version","Check recent changes to normalize_column's dispatch logic for struct fields","Regenerate the trace file if its schema was manually modified","Report a bug with the schema that triggers the panic"],"exampleFix":"// before\nlet DataType::Struct(expected_fields) = expected_field.data_type() else {\n    unreachable!(\"expected_field should be Struct\");\n};\n// after\nlet DataType::Struct(expected_fields) = expected_field.data_type() else {\n    return Err(vec![format!(\n        \"field {path}: expected Struct but found {:?}\",\n        expected_field.data_type()\n    )]);\n};","handlingStrategy":"validation","validationCode":"fn is_struct(field: &arrow_schema::Field) -> bool {\n    matches!(field.data_type(), arrow_schema::DataType::Struct(_))\n}","typeGuard":"fn as_struct_fields(dt: &DataType) -> Option<&Fields> {\n    if let DataType::Struct(f) = dt { Some(f) } else { None }\n}","tryCatchPattern":"if !is_struct(expected_field) {\n    return Err(vec![format!(\"field {path}: expected Struct\")]);\n}","preventionTips":["Read trace files with a matching dbt-tracing version","Regenerate traces after schema format changes","Add round-trip tests for normalize_column over all supported types"],"tags":["arrow","schema","invariant","panic"],"backgroundTag":"internal-invariant-violation","analyzedSha":"0267ce9170576975b76b64ce856b2e5848e96617","analyzedAt":"2026-09-07T21:53:39.732Z","contentChangedAt":"2026-09-07T21:53:39.732Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}