apache/flink · error · IOException

Exactly one of LocalDate and LocalTime is null.

Error message

Exactly one of LocalDate and LocalTime is null.

What it means

LocalDateTimeSerializer splits a LocalDateTime into a LocalDate and a LocalTime and serializes each with its own singleton serializer. On deserialize it reconstructs the pair; the guard rejects the case where exactly one component is null, since that indicates inconsistent/null markers rather than a legitimate null LocalDateTime (both null).

Source

Thrown at flink-core/src/main/java/org/apache/flink/api/common/typeutils/base/LocalDateTimeSerializer.java:84

    @Override
    public void serialize(LocalDateTime record, DataOutputView target) throws IOException {
        if (record == null) {
            LocalDateSerializer.INSTANCE.serialize(null, target);
            LocalTimeSerializer.INSTANCE.serialize(null, target);
        } else {
            LocalDateSerializer.INSTANCE.serialize(record.toLocalDate(), target);
            LocalTimeSerializer.INSTANCE.serialize(record.toLocalTime(), target);
        }
    }

    @Override
    public LocalDateTime deserialize(DataInputView source) throws IOException {
        LocalDate localDate = LocalDateSerializer.INSTANCE.deserialize(source);
        LocalTime localTime = LocalTimeSerializer.INSTANCE.deserialize(source);
        if (localDate == null && localTime == null) {
            return null;
        } else if (localDate == null || localTime == null) {
            throw new IOException("Exactly one of LocalDate and LocalTime is null.");
        } else {
            return LocalDateTime.of(localDate, localTime);
        }
    }

    @Override
    public LocalDateTime deserialize(LocalDateTime reuse, DataInputView source) throws IOException {
        return deserialize(source);
    }

    @Override
    public void copy(DataInputView source, DataOutputView target) throws IOException {
        LocalDateSerializer.INSTANCE.copy(source, target);
        LocalTimeSerializer.INSTANCE.copy(source, target);
    }

    @Override
    public TypeSerializerSnapshot<LocalDateTime> snapshotConfiguration() {

View on GitHub (pinned to 2f3c205e92)

Solutions

  1. Verify the data was written with a compatible LocalDateTimeSerializer version (check serializer snapshot compatibility logs at restore).
  2. If you have a custom serialization path writing these components, ensure both the date and time halves are written or omitted together.
  3. Inspect the restore logs for a serializer schema mismatch (resolveSchemaCompatibility) between writer and reader.
  4. If the checkpoint data is corrupt, discard the savepoint and restart from a known-good state.
  5. Reproduce on a clean job to rule out stream truncation from network/disk errors.
Defensive patterns

Strategy: try-catch

Try / catch

try {
    LocalDateTime value = LocalDateTimeSerializer.INSTANCE.deserialize(source);
} catch (IOException e) {
    if (e.getMessage().contains("LocalDate and LocalTime is null")) {
        log.error("Inconsistent LocalDateTime stream: one of date/time decoded as null; data is corrupt or serializer version mismatched");
    }
    throw e;
}

Prevention

When it happens

Trigger: Deserializing a LocalDateTime from a stream where exactly one of the LocalDate/LocalTime components decoded as null while the other did not — typically stream corruption or a serializer mismatch.

Common situations: Corrupted checkpoint/savepoint bytes; a custom serialization path that wrote inconsistent null markers for the date and time halves; a version skew where LocalDateSerializer/LocalTimeSerializer null handling changed; partial write or truncation of the state stream.

Related errors


AI-assisted analysis of apache/flink@2f3c205e92 (2026-08-14). Data as JSON: /api/errors/555cf2dd50eb9f13. Report an issue: GitHub.