risingwavelabs/risingwave · error · ConnectorError

shard iterator is none

Error message

shard iterator is none

What it means

In `get_shard_iter_inner` (called from `new_shard_iter`), after calling Kinesis `GetShardIterator` the response's optional `shard_iterator` field is expected to be present. If AWS returns success but no iterator (`resp.shard_iterator()` is None), the code `bail!`s with "shard iterator is none". This is wrapped by a retry with exponential backoff (3 attempts) in `new_shard_iter` before ultimately failing.

Source

Thrown at src/connector/src/source/kinesis/source/reader.rs:376

            starting_seq_num: Option<String>,
            starting_timestamp: Option<DateTime>,
            iter_type: ShardIteratorType,
        ) -> Result<String> {
            let resp = client
                .get_shard_iterator()
                .stream_name(stream_name)
                .shard_id(shard_id)
                .shard_iterator_type(iter_type)
                .set_starting_sequence_number(starting_seq_num)
                .set_timestamp(starting_timestamp)
                .send()
                .await
                .context("failed to get kinesis shard iterator")?;

            if let Some(iter) = resp.shard_iterator() {
                Ok(iter.to_owned())
            } else {
                bail!("shard iterator is none")
            }
        }

        self.shard_iter = Some(
            tokio_retry::Retry::spawn(
                exponential_backoff(Duration::from_millis(100), 2, Duration::MAX).take(3),
                || {
                    get_shard_iter_inner(
                        &self.client,
                        &self.stream_name,
                        &self.shard_id,
                        starting_seq_num.clone(),
                        start_timestamp,
                        iter_type.clone(),
                    )
                },
            )
            .await?,

View on GitHub (pinned to 6469eb736d)

Solutions

  1. Wait and retry — the connector already retries 3 times with exponential backoff starting at 100ms; a transient condition usually resolves.
  2. Verify the shard_id is current: resharding invalidates shard lists; restart the source so the enumerator refreshes shards.
  3. Switch startup mode to 'latest' or 'earliest' if a timestamp/sequence position is unavailable for the shard.
  4. If persistent, check the AWS region configuration matches the stream's region.
Defensive patterns

Strategy: retry

Try / catch

// The connector already retries internally; on final failure, wrap with backoff restart
match start_source(source_id).await {
    Err(e) if e.to_string().contains("shard iterator is none") => {
        tokio::time::sleep(Duration::from_secs(30)).await;
        start_source(source_id).await?; // shard state / resharding usually settles
    }
    other => other?;
}

Prevention

When it happens

Trigger: AWS GetShardIterator succeeds with HTTP 200 but omits shard_iterator — typically when the requested starting position is not yet available (TRIM_HORIZON/LATEST edge cases), the shard is in an inconsistent state, or the AWS SDK returns an empty/degenerate response.

Common situations: Recently created or just-resharded (merged/split) shards whose iterators are momentarily unavailable; throttled region endpoints returning empty bodies; very old shards where the requested sequence position no longer exists.

Related errors


AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11). Data as JSON: /api/errors/6e467ead8598cae5. Report an issue: GitHub.