apache/druid · error · ISE

Failed to get shardSpec for interval

Error message

Failed to get shardSpec for interval[%s]

What it means

ShardSpecs maintains a map of intervals to lists of BucketNumberedShardSpec produced during determineShardSpecs. getShardSpec looks up the shard specs for the row's interval and throws ISE when no shard specs were computed for that interval, meaning the row's timestamp bucket was never part of the shard-spec planning phase.

Solutions

  1. Check the offending row's timestamp and the task's granularitySpec intervals; ensure rows fall within configured intervals or enable dropRowOnOutOfInterval / widen the intervals.
  2. Re-run shard-spec determination (determineShardSpecs) before reading rows so the map is fully populated.
  3. Verify queryGranularity matches the data — rows bucketed to a granularity not covered by the shard specs plan will have no entry.
  4. Filter or route out-of-range rows before indexing instead of letting them reach getShardSpec.

Example fix

// before
BucketNumberedShardSpec<?> spec = shardSpecs.getShardSpec(interval, row); // ISE if interval unplanned
// after
if (!shardSpecs.hasShardSpec(interval)) {
  log.warn("Dropping row outside planned intervals: %s", row);
  return null;
}
BucketNumberedShardSpec<?> spec = shardSpecs.getShardSpec(interval, row);
Defensive patterns

Strategy: validation

Validate before calling

if (rows.stream().map(r -> gran.bucketStart(r.getTimestamp())).anyMatch(t -> !plannedIntervals.contains(new Interval(t, gran)))) {
  throw new IllegalArgumentException("Rows exist outside planned shard-spec intervals");
}

Type guard

boolean isPlanned(ShardSpecs specs, Interval interval) { return specs != null && specs.getShardSpecsForInterval(interval) != null && !specs.getShardSpecsForInterval(interval).isEmpty(); }

Try / catch

try {
  return shardSpecs.getShardSpec(interval, row);
} catch (IllegalStateException e) {
  if (e.getMessage().startsWith("Failed to get shardSpec")) {
    log.debug("Row outside planned intervals, dropping: %s", row.getId());
    return null;
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling getShardSpec(interval, row) with an interval that is absent from the map — typically because the input row's timestamp, truncated to queryGranularity, falls into an interval for which no shard specs were determined (e.g. rows outside the configured granularity/intervals of the task), or getShardSpec is invoked before determineShardSpecs populated the map.

Common situations: Ingesting rows whose timestamps fall outside the task's configured intervals (late-arriving or mistimed data with fixOffsetsTimestampGranularity disabled); custom tasks calling getShardSpec against a partially built ShardSpecs map; clock-skewed producers emitting timestamps in unexpected buckets.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


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

Appendix: source

Thrown at indexing-service/src/main/java/org/apache/druid/indexing/common/task/ShardSpecs.java:57

  ShardSpecs(final Map<Interval, List<BucketNumberedShardSpec<?>>> map, Granularity queryGranularity)
  {
    this.map = map;
    this.queryGranularity = queryGranularity;
  }

  /**
   * Return a shardSpec for the given interval and input row.
   *
   * @param interval interval for shardSpec
   * @param row      input row
   *
   * @return a shardSpec
   */
  BucketNumberedShardSpec<?> getShardSpec(Interval interval, InputRow row)
  {
    final List<BucketNumberedShardSpec<?>> shardSpecs = map.get(interval);
    if (shardSpecs == null || shardSpecs.isEmpty()) {
      throw new ISE("Failed to get shardSpec for interval[%s]", interval);
    }
    final long truncatedTimestamp = queryGranularity.bucketStart(row.getTimestamp()).getMillis();
    return (BucketNumberedShardSpec<?>) shardSpecs.get(0).getLookup(shardSpecs).getShardSpec(truncatedTimestamp, row);
  }
}

View on GitHub (pinned to 9b90983fd2)