{"record":{"id":"9910a7fcd87e3d63","repo":"yuliskov/SmartTube","slug":"dates-must-not-be-null","errorCode":null,"errorMessage":"Dates must not be null","messagePattern":"Dates must not be null","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"chatkit/src/main/java/com/stfalcon/chatkit/utils/DateFormatter.java","lineNumber":41,"sourceCode":"\npublic final class DateFormatter {\n    private DateFormatter() {\n        throw new AssertionError();\n    }\n\n    public static String format(Date date, Template template) {\n        return format(date, template.get());\n    }\n\n    public static String format(Date date, String format) {\n        if (date == null) return \"\";\n        return new SimpleDateFormat(format, Locale.getDefault())\n                .format(date);\n    }\n\n    public static boolean isSameDay(Date date1, Date date2) {\n        if (date1 == null || date2 == null) {\n            throw new IllegalArgumentException(\"Dates must not be null\");\n        }\n        Calendar cal1 = Calendar.getInstance();\n        cal1.setTime(date1);\n        Calendar cal2 = Calendar.getInstance();\n        cal2.setTime(date2);\n        return isSameDay(cal1, cal2);\n    }\n\n    public static boolean isSameDay(Calendar cal1, Calendar cal2) {\n        if (cal1 == null || cal2 == null) {\n            throw new IllegalArgumentException(\"Dates must not be null\");\n        }\n        return (cal1.get(Calendar.ERA) == cal2.get(Calendar.ERA) &&\n                cal1.get(Calendar.YEAR) == cal2.get(Calendar.YEAR) &&\n                cal1.get(Calendar.DAY_OF_YEAR) == cal2.get(Calendar.DAY_OF_YEAR));\n    }\n\n    public static boolean isSameYear(Date date1, Date date2) {","sourceCodeStart":23,"sourceCodeEnd":59,"githubUrl":"https://github.com/yuliskov/SmartTube/blob/3de8d90593e0166f012ca18cc3c7ba45bfd68ac4/chatkit/src/main/java/com/stfalcon/chatkit/utils/DateFormatter.java#L23-L59","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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)"],"exampleFix":"// before\npublic Date getCreatedAt() { return mDate; } // null when API omits the timestamp\n\n// after\npublic Date getCreatedAt() { return mDate != null ? mDate : new Date(0); }","handlingStrategy":"validation","validationCode":"static boolean isSameDaySafe(@Nullable Date a, @Nullable Date b) {\n    if (a == null || b == null) return false; // explicit policy for missing dates\n    return DateFormatter.isSameDay(a, b);\n}","typeGuard":"static boolean hasDate(@Nullable IMessage msg) {\n    return msg != null && msg.getCreatedAt() != null;\n}","tryCatchPattern":null,"preventionTips":["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"],"tags":["chatkit","date","null-safety","date-headers"],"backgroundTag":"null-date-argument","analyzedSha":"3de8d90593e0166f012ca18cc3c7ba45bfd68ac4","analyzedAt":"2026-08-22T09:19:26.383Z","schemaVersion":2},"datasetVersion":"2026-08-22T14:17:55.899Z"}