apache/druid · error · IllegalStateException

Failed to add a row with timestamp[%s]

Error message

Failed to add a row with timestamp[%s]

What it means

Thrown by SinglePhaseSubTask.generateAndPushSegments when the IndexIngestionDriver fails to add an input row to the current segment — i.e., the row could not be added to the incremental index while building segments. This indicates a row-level ingestion failure such as the row not fitting into the current segment's schema/partitioning, rather than bad input alone, and Druid surfaces the failing row's timestamp for diagnosis.

Source

Thrown at indexing-service/src/main/java/org/apache/druid/indexing/common/task/batch/parallel/SinglePhaseSubTask.java:444

        if (addResult.isOk()) {
          final boolean isPushRequired = addResult.isPushRequired(
              partitionsSpec.getMaxRowsPerSegment(),
              partitionsSpec.getMaxTotalRowsOr(DynamicPartitionsSpec.DEFAULT_MAX_TOTAL_ROWS)
          );
          if (isPushRequired) {
            // There can be some segments waiting for being published even though any rows won't be added to them.
            // If those segments are not published here, the available space in appenderator will be kept to be small
            // which makes the size of segments smaller.
            final SegmentsAndCommitMetadata pushed = driver.pushAllAndClear(pushTimeout);
            pushedSegments.addAll(pushed.getSegments());
            segmentSchemaMapping.merge(pushed.getSegmentSchemaMapping());
            LOG.info("Pushed [%s] segments and [%s] schemas", pushed.getSegments().size(), segmentSchemaMapping.getSchemaCount());
            LOG.infoSegments(pushed.getSegments(), "Pushed segments");
            LOG.info("SegmentSchema is [%s]", segmentSchemaMapping);
          }
        } else {
          throw new ISE("Failed to add a row with timestamp[%s]", inputRow.getTimestamp());
        }
      }

      final SegmentsAndCommitMetadata pushed = driver.pushAllAndClear(pushTimeout);
      pushedSegments.addAll(pushed.getSegments());
      segmentSchemaMapping.merge(pushed.getSegmentSchemaMapping());
      LOG.info("Pushed [%s] segments and [%s] schemas", pushed.getSegments().size(), segmentSchemaMapping.getSchemaCount());
      LOG.infoSegments(pushed.getSegments(), "Pushed segments");
      LOG.info("SegmentSchema is [%s]", segmentSchemaMapping);
      appenderator.close();

      return new DataSegmentsWithSchemas(pushedSegments, segmentSchemaMapping.isNonEmpty() ? segmentSchemaMapping : null);
    }
    catch (TimeoutException | ExecutionException e) {
      exceptionOccurred = true;
      throw new RuntimeException(e);
    }
    catch (Exception e) {

View on GitHub (pinned to 9b90983fd2)

Solutions

  1. Check the reported timestamp and the subtask's assigned intervals/partitions; fix the input filter or partitionsSpec so rows match the subtask's ranges
  2. Re-run determinePartitions to regenerate partition boundaries if input data shifted between the determine and ingest phases
  3. Verify that clocks and time filtering in the input source do not emit rows outside the task granularity interval
  4. If caused by a driver/index bug, capture the failing row and report with full task logs; consider upgrading Druid

Example fix

// before: rows outside assigned range reach the driver
InputRow row = rowIterator.next();
// after: pre-filter to the subtask's interval/partition range
if (interval.contains(row.getTimestamp()) && range.contains(row.getDimension(partitionDim).get(0))) {
  driver.add(row);
}
Defensive patterns

Strategy: validation

Validate before calling

// pre-filter rows to the subtask's assigned interval and partition range before driver.add
if (!interval.contains(inputRow.getTimestamp())) { continue; }
Object pdv = inputRow.getRaw(partitionDimension);
if (!assignedRange.contains(pdv)) { continue; }

Type guard

boolean isRowInScope(InputRow row, Interval interval, Range<Object> range, String dim) {
  return interval.contains(row.getTimestamp())
      && row.getDimension(dim) != null
      && row.getDimension(dim).size() == 1
      && range.contains(row.getDimension(dim).get(0));
}

Try / catch

catch (ISE e) {
  if (e.getMessage().startsWith("Failed to add a row with timestamp")) {
    log.error("row out of segment scope at %s; check partitionsSpec/interval filters", e.getMessage());
    throw new TaskRetryableException(e); // or fail fast with diagnostics
  } throw e;
}

Prevention

When it happens

Trigger: driver.add(inputRow) returns false (row not added) — e.g., the row's dimensions/timestamp fall outside the shard spec's expected range for the current segment, or the incremental index rejects the row because of schema mismatch with the assigned partition.

Common situations: Range partitioning where a row's partition-dimension value doesn't match the subtask's assigned range; clock issues putting rows outside the task's interval; dimension schema changes mid-run; rows filtered by partitions but not pre-filtered by the input source reader.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


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