{"record":{"id":"359b86fa70db1cc2","repo":"apache/druid","slug":"cannot-get-time-from-type-s","errorCode":null,"errorMessage":"Cannot get time from type[%s]","messagePattern":"Cannot get time from type\\[(.+?)\\]","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"processing/src/main/java/org/apache/druid/query/timeboundary/TimeBoundaryResultValue.java","lineNumber":115,"sourceCode":"           \"value=\" + value +\n           '}';\n  }\n\n  @Nullable\n  private DateTime getDateTimeValue(@Nullable Object val)\n  {\n    if (val == null) {\n      return null;\n    }\n\n    if (val instanceof DateTime) {\n      return (DateTime) val;\n    } else if (val instanceof String) {\n      return DateTimes.of((String) val);\n    } else if (val instanceof Long) {\n      return DateTimes.utc((Long) val);\n    } else {\n      throw new IAE(\"Cannot get time from type[%s]\", val.getClass());\n    }\n  }\n}\n","sourceCodeStart":97,"sourceCodeEnd":119,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/processing/src/main/java/org/apache/druid/query/timeboundary/TimeBoundaryResultValue.java#L97-L119","documentation":"TimeBoundaryResultValue.getDateTimeValue() converts the MIN_TIME/MAX_TIME entry into a joda DateTime. It supports DateTime, String (ISO), and Long (epoch millis); any other stored type is unsupported and throws IAE(\"Cannot get time from type[%s]\").","triggerScenarios":"A TimeBoundaryQuery result map whose MIN_TIME or MAX_TIME entry is neither DateTime, String, nor Long — e.g. an Integer, Date, byte[] from custom JSON deserialization, or a value put in the map by custom code.","commonSituations":"Custom storage/deserialization plugins producing Integer timestamps instead of Long, manually built result maps with java.util.Date, JSON numbers deserialized into non-Long types by non-standard mappers.","solutions":["Ensure the map value is a Long (epoch millis), String (ISO-8601), or DateTime before calling getMaxTime()/getMinTime()","Normalize the value: DateTimes.utc(((Number) v).longValue()) for numeric types","Fix the serializer/deserializer so timestamps round-trip as Long or String","Pass the value through DateTimes.of/StringUtil conversion yourself before building the result"],"exampleFix":"// before\nnew TimeBoundaryResultValue(ImmutableMap.of(TimeBoundaryQuery.MAX_TIME, (int) millis)).getMaxTime(); // throws\n// after\nnew TimeBoundaryResultValue(ImmutableMap.of(TimeBoundaryQuery.MAX_TIME, millis)).getMaxTime();","handlingStrategy":"validation","validationCode":"Object v = map.get(TimeBoundaryQuery.MIN_TIME);\nboolean safe = v instanceof DateTime || v instanceof String || v instanceof Long || v instanceof Integer;","typeGuard":"static boolean isSupportedTimeType(Object v) {\n  return v instanceof DateTime || v instanceof String || v instanceof Number;\n}","tryCatchPattern":"try { DateTime t = value.getMinTime(); } catch (IllegalArgumentException e) { log.warn(\"Unsupported time type in result\", e); t = null; }","preventionTips":["Serialize timestamps as Long epoch-millis or ISO strings","Avoid java.util.Date/Integer in custom result maps","Test custom deserializers against TimeBoundaryResultValue"],"tags":["druid","timeboundary","type-mismatch","datetime"],"backgroundTag":"invalid-argument-format","analyzedSha":"9b90983fd291f26935af934383ce360473179e4d","analyzedAt":"2026-09-07T13:32:30.957Z","contentChangedAt":"2026-09-07T13:32:30.957Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}