{"record":{"id":"7efa3ab0a9478551","repo":"apache/seatunnel","slug":"data-type-cast-field-7efa3a","errorCode":"DATA_TYPE_CAST_FIELD","errorMessage":"Value type must be STRING when target column type is LIST.","messagePattern":"Value type must be STRING when target column type is LIST\\.","errorType":"error_code","errorClass":"SensorsDataException","httpStatus":null,"severity":"error","filePath":"seatunnel-connectors-v2/connector-sensorsdata/src/main/java/org/apache/seatunnel/connectors/sensorsdata/format/utils/TypeUtil.java","lineNumber":145,"sourceCode":"            case LIST_COMMA:\n                return toList(source, ',');\n            case LIST_SEMICOLON:\n                return toList(source, ';');\n            case TIMESTAMP:\n                return toTimestamp(source, targetType, extra);\n            case DATE:\n                return toDate(source, targetType);\n            case STRING:\n            default:\n                return toString(source);\n        }\n    }\n\n    private static List<String> toList(Object str, char sep) {\n        if (str instanceof String) {\n            return Arrays.asList(StringUtils.split((String) str, sep));\n        } else {\n            throw new SensorsDataException(\n                    SensorsDataErrorCode.DATA_TYPE_CAST_FIELD,\n                    \"Value type must be STRING when target column type is LIST.\");\n        }\n    }\n\n    private static Object toTimestamp(\n            Object source, SensorsDataTypes.DataTypes targetType, String format) {\n        if (source instanceof Date) {\n            return ((Date) source).getTime();\n        }\n        if (source instanceof Number) {\n            return source;\n        }\n        if (source instanceof LocalDate) {\n            return ((LocalDate) source)\n                    .atStartOfDay(ZoneId.systemDefault())\n                    .toInstant()\n                    .toEpochMilli();","sourceCodeStart":127,"sourceCodeEnd":163,"githubUrl":"https://github.com/apache/seatunnel/blob/cf67b549a7a6c35fa0beb12d83c62892427ea919/seatunnel-connectors-v2/connector-sensorsdata/src/main/java/org/apache/seatunnel/connectors/sensorsdata/format/utils/TypeUtil.java#L127-L163","documentation":"TypeUtil.toList converts a source value into a SensorsData LIST column by splitting a delimited string. It only accepts a java.lang.String; any other runtime type (numbers, arrays, collections, dates) is rejected with SensorsDataException code DATA_TYPE_CAST_FIELD. This guards the Sensors inf-sdk, which requires LIST target columns to be fed string input split by the configured separator.","triggerScenarios":"toTargetType(source, LIST/LIST_COMMA/LIST_SEMICOLON) is called with a source value that is not a String — e.g. the SeaTunnel field is an INT, ARRAY, or DATE, while the target column config declares a LIST type (list, list-comma, or list-semicolon).","commonSituations":"Mismatches between the source table schema and the sink's target-column type mapping (e.g. source column is an array of strings but target is list); upstream schema evolution changed a column from STRING to a non-string type; users expect automatic coercion that the connector does not perform.","solutions":["Change the target column type in the sink config from list to string, or cast the source column to STRING upstream before the sink.","Use a transform (e.g. Cast/SQL transform) to convert the field to STRING prior to writing.","Update the source schema so the column is declared as STRING when it feeds a LIST target.","If the source is genuinely a list, serialize it to a delimited string (joining with the separator) upstream."],"exampleFix":"// before: source field is an array feeding a LIST target\n{\"source_field\": \"tags_array\", \"target\": \"tags\", \"type\": \"list\"} // throws\n// after: cast to string first (transform) or declare source as STRING\n{\"source_field\": \"tags_array\", \"target\": \"tags\", \"type\": \"string\"}\n// or transform: CAST(tags_array AS STRING) before the sink","handlingStrategy":"type-guard","validationCode":"if (!(value instanceof String)) {\n    throw new IllegalArgumentException(\n        \"Column '\" + name + \"' must be STRING to feed a LIST target; got \" + value.getClass().getSimpleName());\n}","typeGuard":"boolean isStringForListTarget(Object v) { return v instanceof String; }","tryCatchPattern":"try {\n    Object converted = TypeUtil.toTargetType(value, \"list\");\n} catch (SensorsDataException e) {\n    if (SensorsDataErrorCode.DATA_TYPE_CAST_FIELD.equals(e.getErrorCode())) {\n        // fall back to string conversion\n        converted = String.valueOf(value);\n    }\n}","preventionTips":["Match source column types to the target-column type mapping in the sink config.","Cast non-string sources to STRING via a transform before the sink.","Avoid declaring LIST target columns for source fields that may change type."],"tags":["sensorsdata","type-conversion","list-column"],"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"}