apache/druid · error · IllegalStateException

Partition [%s] has not been assigned

Error message

Partition [%s] has not been assigned

What it means

partitionSeek looks up the PartitionResource for the given StreamPartition and throws this ISE if none has been assigned. A seek (and the public seek/seekToEarliest/seekToLatest paths that route through it) is only legal after the partition was assigned to this supplier.

Source

Thrown at extensions-core/kinesis-indexing-service/src/main/java/org/apache/druid/indexing/kinesis/KinesisRecordSupplier.java:915

  public boolean isAnyFetchActive()
  {
    return partitionResources.values()
                             .stream()
                             .map(pr -> pr.currentFetch)
                             .anyMatch(fetch -> (fetch != null && !fetch.isDone()));
  }

  /**
   * Check that a {@link PartitionResource} has been assigned to this record supplier, and if so call
   * {@link PartitionResource#seek} to move it to the latest offsets. Note that this method does not restart background
   * fetch, which should have been stopped prior to calling this method by a call to
   * {@link #filterBufferAndResetBackgroundFetch}.
   */
  private void partitionSeek(StreamPartition<String> partition, String sequenceNumber, ShardIteratorType iteratorEnum)
  {
    PartitionResource resource = partitionResources.get(partition);
    if (resource == null) {
      throw new ISE("Partition [%s] has not been assigned", partition);
    }
    resource.seek(iteratorEnum, sequenceNumber);
  }

  /**
   * Given a partition and a {@link ShardIteratorType}, create a shard iterator and fetch
   * {@link #GET_SEQUENCE_NUMBER_RECORD_COUNT} records and return the first sequence number from the result set.
   * This method is thread safe as it does not depend on the internal state of the supplier (it doesn't use the
   * {@link PartitionResource} which have been assigned to the supplier), and the Kinesis client is thread safe.
   * <p>
   * When there are no records at the offset corresponding to the ShardIteratorType,
   *    If shard is closed, return custom EOS sequence marker
   *    While getting the earliest sequence number, return a custom marker corresponding to TRIM_HORIZON
   *    While getting the most recent sequence number, return a custom marker corresponding to LATEST
   */
  @Nullable
  private String getSequenceNumber(StreamPartition<String> partition, ShardIteratorType iteratorEnum)
  {

View on GitHub (pinned to 9b90983fd2)

Solutions

  1. Ensure assign(...) (or setStream/partition assignment) is called with the partition before seeking it
  2. List current shards via getPartitionIds and seek only shards present in the assignment
  3. Refresh shard map after resharding — closed shards cannot be seeked by iterator; use their ending sequence number
  4. Verify the partition key (stream name + shard id) matches exactly what was assigned

Example fix

// before
supplier.seek(partition, sequenceNumber);
// after
if (assignedPartitions.contains(partition)) {
  supplier.seek(partition, sequenceNumber);
} else {
  LOG.warn("Skipping seek for unassigned partition %s", partition);
}
Defensive patterns

Strategy: validation

Validate before calling

Set<StreamPartition<String>> assigned = supplier.getAssignment();
if (assigned == null || !assigned.contains(partition)) {
  throw new IllegalArgumentException("seek requires partition assigned: " + partition);
}

Type guard

static boolean canSeek(KinesisRecordSupplier s, StreamPartition<String> p) {
  return s.getAssignment() != null && s.getAssignment().contains(p);
}

Try / catch

try {
  supplier.seek(partition, seqNum);
} catch (ISE e) {
  if (e.getMessage().contains("has not been assigned")) {
    supplier.assign(partitions); // re-assign then retry
    supplier.seek(partition, seqNum);
  } else throw e;
}

Prevention

When it happens

Trigger: Calling seek/seekToEarliest/seekToLatest (or partitionSeek directly) with a StreamPartition that was never added via assign/partition assignment, or after assignment was cleared.

Common situations: Seeking a shard that was split/merged away and is no longer in the assignment list; task restart where assignment did not include the partition in metadata; typos or stale partitions after stream resharding.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


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