apache/druid · error · UnsupportedOperationException (UOE)

Unable to get first event timestamp using result format of

Error message

Unable to get first event timestamp using result format of [%s]

What it means

getFirstEventTimestamp only supports RESULT_FORMAT_LIST and RESULT_FORMAT_COMPACTED_LIST. Any other result format has no defined way to extract a first-event timestamp, so it throws an UnsupportedOperationException identifying the unsupported format.

Solutions

  1. Use list or compacted-list result formats when time-ordering scan results.
  2. Convert the result value to a supported format before calling getFirstEventTimestamp in custom code.
  3. If a new result format is needed, extend getFirstEventTimestamp (or upstream it) rather than passing it through.

Example fix

// before
if (sv.getResultFormat() == RESULT_FORMAT_VALUE_VECTOR) { sv.getFirstEventTimestamp(format); }
// after
if (sv.getResultFormat() == RESULT_FORMAT_COMPACTED_LIST || sv.getResultFormat() == RESULT_FORMAT_LIST) {
  long ts = sv.getFirstEventTimestamp(sv.getResultFormat());
}
Defensive patterns

Strategy: type-guard

Validate before calling

if (format != ResultFormat.RESULT_FORMAT_LIST && format != ResultFormat.RESULT_FORMAT_COMPACTED_LIST) {
  throw new IllegalArgumentException("timestamp extraction requires list/compacted-list format");
}

Type guard

boolean timestampExtractable(ScanQuery.ResultFormat f) {
  return f == ResultFormat.RESULT_FORMAT_LIST || f == ResultFormat.RESULT_FORMAT_COMPACTED_LIST;
}

Try / catch

try {
  long ts = sv.getFirstEventTimestamp(format);
} catch (UnsupportedOperationException e) {
  if (e.getMessage().contains("Unable to get first event timestamp")) { /* convert format or skip ordering */ }
  else throw e;
}

Prevention

When it happens

Trigger: Calling getFirstEventTimestamp (directly, or via stableLimitingSort/comparison) on a ScanResultValue whose resultFormat is neither list nor compacted-list — e.g. RESULT_FORMAT_VALUE_VECTOR results fed into the time-ordering path.

Common situations: Custom/extension result formats used with time-ordered scans; misconfigured queries whose resultFormat was changed after construction.

Related errors


AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07). Data as JSON: /api/errors/8881cfbdc8aaf5c2. Report an issue: GitHub.

Appendix: source

Thrown at processing/src/main/java/org/apache/druid/query/scan/ScanResultValue.java:114


  public long getFirstEventTimestamp(ScanQuery.ResultFormat resultFormat)
  {
    if (resultFormat.equals(ScanQuery.ResultFormat.RESULT_FORMAT_LIST)) {
      Object timestampObj = ((Map<String, Object>) ((List<Object>) this.getEvents()).get(0)).get(ColumnHolder.TIME_COLUMN_NAME);
      if (timestampObj == null) {
        throw new ISE("Unable to compare timestamp for rows without a time column");
      }
      return DimensionHandlerUtils.convertObjectToLong(timestampObj);
    } else if (resultFormat.equals(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST)) {
      int timeColumnIndex = this.getColumns().indexOf(ColumnHolder.TIME_COLUMN_NAME);
      if (timeColumnIndex == -1) {
        throw new ISE("Unable to compare timestamp for rows without a time column");
      }
      List<Object> firstEvent = (List<Object>) ((List<Object>) this.getEvents()).get(0);
      return DimensionHandlerUtils.convertObjectToLong(firstEvent.get(timeColumnIndex));
    }
    throw new UOE("Unable to get first event timestamp using result format of [%s]", resultFormat.toString());
  }

  public List<ScanResultValue> toSingleEventScanResultValues()
  {
    List<ScanResultValue> singleEventScanResultValues = new ArrayList<>();
    List<Object> events = (List<Object>) this.getEvents();
    for (Object event : events) {
      singleEventScanResultValues.add(new ScanResultValue(segmentId, columns, Collections.singletonList(event), rowSignature));
    }
    return singleEventScanResultValues;
  }

  @Override
  public boolean equals(Object o)
  {
    if (this == o) {
      return true;
    }

View on GitHub (pinned to 9b90983fd2)