{"record":{"id":"c3a25b330b41269e","repo":"apache/iceberg","slug":"cannot-convert-date-value","errorCode":null,"errorMessage":"Cannot convert date: ${value}","messagePattern":"Cannot convert date: (.+?)","errorType":"exception","errorClass":"ConnectException","httpStatus":null,"severity":"error","filePath":"kafka-connect/kafka-connect/src/main/java/org/apache/iceberg/connect/data/RecordConverter.java","lineNumber":552,"sourceCode":"      return (ByteBuffer) value;\n    }\n    throw new IllegalArgumentException(\"Cannot convert to binary: \" + value.getClass().getName());\n  }\n\n  @SuppressWarnings(\"JavaUtilDate\")\n  protected LocalDate convertDateValue(Object value) {\n    if (value instanceof Number) {\n      int days = ((Number) value).intValue();\n      return DateTimeUtil.dateFromDays(days);\n    } else if (value instanceof String) {\n      return LocalDate.parse((String) value);\n    } else if (value instanceof LocalDate) {\n      return (LocalDate) value;\n    } else if (value instanceof Date) {\n      int days = (int) (((Date) value).getTime() / 1000 / 60 / 60 / 24);\n      return DateTimeUtil.dateFromDays(days);\n    }\n    throw new ConnectException(\"Cannot convert date: \" + value);\n  }\n\n  @SuppressWarnings(\"JavaUtilDate\")\n  protected LocalTime convertTimeValue(Object value) {\n    if (value instanceof Number) {\n      long millis = ((Number) value).longValue();\n      return DateTimeUtil.timeFromMicros(millis * 1000);\n    } else if (value instanceof String) {\n      return LocalTime.parse((String) value);\n    } else if (value instanceof LocalTime) {\n      return (LocalTime) value;\n    } else if (value instanceof Date) {\n      long millis = ((Date) value).getTime();\n      return DateTimeUtil.timeFromMicros(millis * 1000);\n    }\n    throw new ConnectException(\"Cannot convert time: \" + value);\n  }\n","sourceCodeStart":534,"sourceCodeEnd":570,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/kafka-connect/kafka-connect/src/main/java/org/apache/iceberg/connect/data/RecordConverter.java#L534-L570","documentation":"RecordConverter.convertDateValue throws this ConnectException when a value mapped to an Iceberg Date column is not a Number (days since epoch), LocalDate, java.util.Date, or a parseable date string. The sink cannot interpret the value as a calendar date.","triggerScenarios":"A Date field receives a nested struct, map, boolean, or arbitrary object; or a String that fails date parsing reaches convertDateValue via convertValue or ts (timestamp-to-date coercion).","commonSituations":"Producer schema changed a date field to a complex type; Connect's JSON converter delivered an unparsed string or object; an SMT cast a timestamp into the wrong field that the sink maps to Date.","solutions":["Ensure the Connect schema declares the field as int32 with the Date logical type (or int32 days / string date)","Use TimestampConverter SMT to normalize the value to Date/unix time before the sink","Fix the source record so the date is an ISO-8601 string or epoch-days number","Verify the field mapping in the connector config hasn't shifted to a different field"],"exampleFix":"// before\nSchemaBuilder.string().build(); // \"not-a-date\" reaches convertDateValue\n// after\nDate.Builder logical = Date.builder().schema(SchemaBuilder.int32().build()); // epoch days","handlingStrategy":"validation","validationCode":"// check before sink\nObject v = record.value().get(\"dateField\");\nif (!(v instanceof Number || v instanceof LocalDate || v instanceof java.util.Date || v instanceof String)) {\n  throw new IllegalStateException(\"Date field bad type: \" + (v == null ? \"null\" : v.getClass()));\n}","typeGuard":"static boolean isDateCompatible(Object v) {\n  return v == null || v instanceof Number || v instanceof LocalDate\n      || v instanceof java.util.Date || v instanceof String;\n}","tryCatchPattern":"try {\n  converter.convertValue(value, Types.DateType.get());\n} catch (ConnectException e) {\n  log.error(\"Date conversion failed: \" + e.getMessage(), e);\n  // send to dead-letter queue instead of failing the task\n}","preventionTips":["Use Connect Date logical type (int32 epoch days)","Run TimestampConverter SMT for temporal normalization","Pin producer schema in Schema Registry to the Date logical type","Test schema evolution changes against the sink before rollout"],"tags":["kafka-connect","date","type-mismatch"],"backgroundTag":"invalid-date-format","analyzedSha":"86d9c8fc543e7c56c9f624eb725f76c9baff9570","analyzedAt":"2026-09-12T00:46:39.097Z","contentChangedAt":"2026-09-12T00:46:39.097Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}