yuliskov/SmartTube · error · IllegalArgumentException
Dates must not be null
Error message
Dates must not be null
What it means
Chatkit uses isSameDay(Date, Date) to place date headers between messages: each message's date is compared with the previous one's, and null dates would only produce a less helpful NPE inside Calendar.setTime, so the method fails fast with IllegalArgumentException. The null almost always originates in your data — IMessage.getCreatedAt() or the previous message's date — not in the formatter.
Source
Thrown at chatkit/src/main/java/com/stfalcon/chatkit/utils/DateFormatter.java:41
public final class DateFormatter {
private DateFormatter() {
throw new AssertionError();
}
public static String format(Date date, Template template) {
return format(date, template.get());
}
public static String format(Date date, String format) {
if (date == null) return "";
return new SimpleDateFormat(format, Locale.getDefault())
.format(date);
}
public static boolean isSameDay(Date date1, Date date2) {
if (date1 == null || date2 == null) {
throw new IllegalArgumentException("Dates must not be null");
}
Calendar cal1 = Calendar.getInstance();
cal1.setTime(date1);
Calendar cal2 = Calendar.getInstance();
cal2.setTime(date2);
return isSameDay(cal1, cal2);
}
public static boolean isSameDay(Calendar cal1, Calendar cal2) {
if (cal1 == null || cal2 == null) {
throw new IllegalArgumentException("Dates must not be null");
}
return (cal1.get(Calendar.ERA) == cal2.get(Calendar.ERA) &&
cal1.get(Calendar.YEAR) == cal2.get(Calendar.YEAR) &&
cal1.get(Calendar.DAY_OF_YEAR) == cal2.get(Calendar.DAY_OF_YEAR));
}
public static boolean isSameYear(Date date1, Date date2) {View on GitHub (pinned to 3de8d90593)
Solutions
- Make getCreatedAt() always return a non-null Date, defaulting to new Date() or new Date(0)
- Wrap comparisons in a null-safe helper that decides same-day semantics before calling DateFormatter
- Fix the upstream parsing that produces the null (format or timezone mismatch)
Example fix
// before
public Date getCreatedAt() { return mDate; } // null when API omits the timestamp
// after
public Date getCreatedAt() { return mDate != null ? mDate : new Date(0); } Defensive patterns
Strategy: validation
Validate before calling
static boolean isSameDaySafe(@Nullable Date a, @Nullable Date b) {
if (a == null || b == null) return false; // explicit policy for missing dates
return DateFormatter.isSameDay(a, b);
} Type guard
static boolean hasDate(@Nullable IMessage msg) {
return msg != null && msg.getCreatedAt() != null;
} Prevention
- Make getCreatedAt() non-null on every message and dialog model
- Default missing timestamps to a sentinel (new Date(0)) at the mapping layer, not at render time
- Add null-date contract tests for models fed into the adapter
When it happens
Trigger: A message model whose getCreatedAt() returns null (missing or unparsable backend timestamp, locally appended pending message); a custom date-header flow passing the previous element's null date on the first comparison.
Common situations: API responses where the timestamp field is optional or the format mismatches the parser so the mapped Date stays null; optimistic sends with unset dates; dialogs whose last message payload lacks a date.
Related errors
- ContentChecker cannot be null when using custom content type
- SelectionListener must not be null. Use `disableSelectionMod
- You can't set adapter to DialogsList. Use #setAdapter(Dialog
- content type must be greater or less than '0'!
- Wrong message view type. Please, report this issue on GitHub
AI-assisted analysis of yuliskov/SmartTube@3de8d90593 (2026-08-22).
Data as JSON: /api/errors/9910a7fcd87e3d63.
Report an issue: GitHub.