{"record":{"id":"c7d90029d561fbb3","repo":"apache/seatunnel","slug":"cannot-convert-to-struct","errorCode":null,"errorMessage":"Cannot convert to struct: ","messagePattern":"Cannot convert to struct: ","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"seatunnel-connectors-v2/connector-iceberg/src/main/java/org/apache/seatunnel/connectors/seatunnel/iceberg/data/RowConverter.java","lineNumber":118,"sourceCode":"        return convertStructValue(row, rowType, tableSchema.asStruct(), -1, wrapper);\n    }\n\n    protected GenericRecord convertStructValue(\n            Object value,\n            SeaTunnelDataType<?> fromType,\n            Types.StructType schema,\n            int parentFieldId,\n            SchemaChangeWrapper wrapper) {\n        switch (fromType.getSqlType()) {\n            case ROW:\n                return convertToStruct(\n                        (SeaTunnelRow) value,\n                        (SeaTunnelRowType) fromType,\n                        schema,\n                        parentFieldId,\n                        wrapper);\n            default:\n                throw new IllegalArgumentException(\n                        \"Cannot convert to struct: \" + fromType.getSqlType().name());\n        }\n    }\n\n    /** Convert RowType */\n    private GenericRecord convertToStruct(\n            SeaTunnelRow row,\n            SeaTunnelRowType fromType,\n            Types.StructType schema,\n            int structFieldId,\n            SchemaChangeWrapper wrapper) {\n        GenericRecord result = GenericRecord.create(schema);\n        String[] fieldNames = fromType.getFieldNames();\n        for (int i = 0; i < fieldNames.length; i++) {\n            String recordField = fieldNames[i];\n            Type afterType = SchemaUtils.toIcebergType(fromType.getFieldType(i));\n            Types.NestedField tableField = lookupStructField(recordField, schema, structFieldId);\n            // add column","sourceCodeStart":100,"sourceCodeEnd":136,"githubUrl":"https://github.com/apache/seatunnel/blob/cf67b549a7a6c35fa0beb12d83c62892427ea919/seatunnel-connectors-v2/connector-iceberg/src/main/java/org/apache/seatunnel/connectors/seatunnel/iceberg/data/RowConverter.java#L100-L136","documentation":"RowConverter.convertStructValue dispatches on the SeaTunnel SqlType of the value being converted into an Iceberg struct; only ROW (SeaTunnelRow) is convertible, anything else reaches default and throws IllegalArgumentException naming the SqlType.","triggerScenarios":"Calling convert()/convertValue() with a fromType whose SqlType is not ROW at a position where the target Iceberg type is a struct (e.g. mapping a map/array/string into a struct field).","commonSituations":"SeaTunnel-to-Iceberg schema mismatches where a nested Iceberg struct field is fed by a non-row SeaTunnel column; wrong sink schema config or upstream transform producing a different shape.","solutions":["Align the SeaTunnel source/transform schema so struct fields carry SeaTunnelRowType (ROW).","Wrap non-row values into a SeaTunnelRow matching the struct schema before writing.","Change the Iceberg table schema to a non-struct type matching the data.","Catch IllegalArgumentException and log/reject the offending record."],"exampleFix":"// before\nrow.setField(i, someString); // struct field\n// after\nrow.setField(i, new SeaTunnelRow(new Object[]{...})); // SeaTunnelRowType for struct field","handlingStrategy":"type-guard","validationCode":"if (fromType.getSqlType() != SqlType.ROW) { throw new IllegalArgumentException(\"Expected ROW for struct field, got \" + fromType.getSqlType()); }","typeGuard":"boolean isRow(Object v, SeaTunnelType<?> t) { return t instanceof SeaTunnelRowType && v instanceof SeaTunnelRow; }","tryCatchPattern":"try { record = converter.convert(row, fromType, schema); } catch (IllegalArgumentException e) { log.error(\"Struct conversion failed: {}\", e.getMessage()); }","preventionTips":["Match SeaTunnelRowType shape to Iceberg struct schema","Use transforms to reshape data into ROW before the sink","Validate schemas at job startup"],"tags":["iceberg","type-mismatch","row-conversion","schema"],"backgroundTag":"type-mismatch","analyzedSha":"cf67b549a7a6c35fa0beb12d83c62892427ea919","analyzedAt":"2026-09-10T21:44:55.265Z","contentChangedAt":"2026-09-10T21:44:55.265Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}