apache/seatunnel · warning

convert target data type error. source

Error message

convert target data type error. source:{}, targetType:{}

What it means

In Apache SeaTunnel's SensorsData connector, TypeUtil.toTimestamp() converts a field value to an epoch-millisecond timestamp for the SensorsData (zhugeio) inf-sdk. When the source value cannot be interpreted as a Date, Number, LocalDate, LocalDateTime, or a date string matching one of the supported formatters (or a custom `extra` pattern), the conversion fails. This is NOT an exception: the method logs 'convert target data type error. source:{}, targetType:{}' at WARN level and returns the original value unchanged, so the field is sent to SensorsData with its raw, unconverted type.

Solutions

  1. Set the TIMESTAMP column's extra format option in the connector schema to a DateTimeFormatter pattern matching your data (e.g. "yyyy-MM-dd'T'HH:mm:ssXXX").
  2. Normalize the date string upstream (transform) into one of the supported patterns: yyyy-MM-dd HH:mm:ss, yyyy-MM-dd HH:mm:ss.SSS, yyyy-MM-dd, yyyyMMdd_HHmmss, yyyyMMdd, or yyyy-MM-dd HH:mm.
  3. Check the WARN log line to see the exact offending source value and target type, then fix the source data or mapping.
  4. If the field is not really a timestamp, change the schema type to STRING so no conversion is attempted.

Example fix

// before: schema maps event_time as TIMESTAMP but data is ISO-8601
// 2024-01-15T10:30:00Z  -> conversion fails, value passed through as String

// after: declare the extra format for the TIMESTAMP field
// fields { event_time = TIMESTAMP }
// with extra format option set to:
// "yyyy-MM-dd'T'HH:mm:ssXXX"
// or pre-normalize the value: 2024-01-15 10:30:00
Defensive patterns

Strategy: validation

Validate before calling

// Java: verify before writing a TIMESTAMP field
private static boolean isValidTimestamp(Object v) {
    return v instanceof java.util.Date
        || v instanceof Number
        || v instanceof java.time.LocalDate
        || v instanceof java.time.LocalDateTime
        || (v instanceof String s && !s.isBlank() && TypeUtil.tryParsePatterns(s)); // matches yyyy-MM-dd[ HH:mm:ss[.SSS]] etc.
}
// call: if (!isValidTimestamp(value)) { normalize(value); }

Type guard

private static boolean isTimestampConvertible(Object v) {
    if (v == null) return true; // null short-circuits in toTargetType
    return v instanceof java.util.Date || v instanceof Number
        || v instanceof java.time.LocalDate || v instanceof java.time.LocalDateTime
        || (v instanceof String && v.toString().matches("\\d{4}-\\d{2}-\\d{2}( \\d{2}:\\d{2}(:\\d{2}(\\.\\d{3})?)?)?|\\d{8}(_\\d{6})?"));
}

Prevention

When it happens

Trigger: TypeUtil.toTimestamp(source, TIMESTAMP, extra) is reached via toTargetType() when the schema maps a column to TIMESTAMP but the runtime value is a String that matches none of the internal patterns (yyyy-MM-dd HH:mm:ss.SSS, yyyy-MM-dd HH:mm:ss, yyyy-MM-dd HH:mm, yyyy-MM-dd, yyyyMMdd_HHmmss, yyyyMMdd) nor the custom `extra` DateTimeFormatter pattern; e.g. an ISO-8601 string like '2024-01-15T10:30:00Z' or a locale-formatted date.

Common situations: Upstream data (CSV/JSON/Kafka) carries dates in ISO-8601 or RFC-3339 format with 'T' separator or timezone suffix, which the hardcoded SeaTunnel formatters do not accept; user forgets to set the TIMESTAMP extra format option; source column is empty or contains 'N/A'/'null' strings; timezone/locale differences shift the expected pattern.

Related errors


AI-assisted analysis of apache/seatunnel@cf67b549a7 (2026-09-10). Data as JSON: /api/errors/9a47dec8bd7bcd7a. Report an issue: GitHub.

Appendix: source

Thrown at seatunnel-connectors-v2/connector-sensorsdata/src/main/java/org/apache/seatunnel/connectors/sensorsdata/format/utils/TypeUtil.java:183

        if (source instanceof LocalDateTime) {
            return ((LocalDateTime) source)
                    .atZone(ZoneId.systemDefault())
                    .toInstant()
                    .toEpochMilli();
        }
        if (source instanceof String) {
            Long timestamp;
            if (format == null) {
                timestamp = tryParse((String) source);
            } else {
                DateTimeFormatter formatter = parseDateTimeFormatter(format);
                timestamp = tryParse((String) source, formatter);
            }
            if (timestamp != null) {
                return timestamp;
            }
        }
        log.warn(TRANSFORM_WARN_INFO, source, targetType);
        return source;
    }

    private static Object toBoolean(Object source, SensorsDataTypes.DataTypes targetType) {
        if (source instanceof Boolean) {
            return source;
        }
        if (source instanceof Number) {
            return !Objects.equal(0, source)
                    && !Objects.equal(0F, source)
                    && !Objects.equal(0D, source)
                    && !Objects.equal(0L, source);
        }
        if (source instanceof String) {
            return StringUtils.equalsIgnoreCase("true", source.toString());
        }
        log.warn(TRANSFORM_WARN_INFO, source, targetType);
        return source;

View on GitHub (pinned to cf67b549a7)