apache/druid · error · RuntimeException
RuntimeException
Error message
RuntimeException
What it means
fetchRecords catches SdkException and classifies it via AWSClientUtil.isClientExceptionRecoverable. Recoverable ones are retried after EXCEPTION_RETRY_DELAY_MS; unrecoverable ones are logged as 'will not retry' and rethrown as a RuntimeException wrapping the SDK exception, which fails the fetch loop.
Source
Thrown at extensions-core/kinesis-indexing-service/src/main/java/org/apache/druid/indexing/kinesis/KinesisRecordSupplier.java:366
if (recordsResult != null) {
shardIterator = recordsResult.nextShardIterator(); // will be null if the shard has been closed
scheduleBackgroundFetch(fetchDelayMillis);
} else {
throw new ISE("can't reschedule fetch records runnable, recordsResult is null??");
}
}
catch (ResourceNotFoundException | InvalidArgumentException e) {
// aws errors
log.error(e, "encounted AWS error while attempting to fetch records, will not retry");
throw e;
}
catch (SdkException e) {
if (AWSClientUtil.isClientExceptionRecoverable(e)) {
log.warn(e, "encounted unknown recoverable AWS exception, retrying in [%,dms]", EXCEPTION_RETRY_DELAY_MS);
scheduleBackgroundFetch(EXCEPTION_RETRY_DELAY_MS);
} else {
log.warn(e, "encounted unknown unrecoverable AWS exception, will not retry");
throw new RuntimeException(e);
}
}
catch (Throwable e) {
// non transient errors
log.error(e, "unknown fetchRecords exception, will not retry");
throw new RuntimeException(e);
}
};
}
private void seek(ShardIteratorType iteratorEnum, String sequenceNumber)
{
log.debug(
"Seeking partition [%s] to [%s]",
streamPartition.getPartitionId(),
sequenceNumber != null ? sequenceNumber : iteratorEnum.toString()
);View on GitHub (pinned to 9b90983fd2)
Solutions
- Read the wrapped SdkException cause and its error code; fix the underlying AWS-side problem (credentials, permissions, stream existence)
- Verify druid kinesis consumer AWS accessKey/secretKey/region config
- Restart the task after fixing AWS configuration — the error is deliberately non-retried
- Add the error code to isClientExceptionRecoverable handling if it is actually transient
Example fix
// before
throw new RuntimeException(e);
// after
if (e.errorCode().equals("ThrottlingException")) {
scheduleBackgroundFetch(EXCEPTION_RETRY_DELAY_MS);
} else {
throw new RuntimeException(e);
} Defensive patterns
Strategy: retry
Validate before calling
// verify credentials and stream exist before consuming GetRecordsPermissionCheck: kinesisClient.describeStreamSummary(DescribeStreamRequest.builder().streamName(stream).build());
Type guard
static boolean unrecoverableSdkError(Throwable t) {
return t instanceof RuntimeException && t.getCause() instanceof SdkException
&& !AWSClientUtil.isClientExceptionRecoverable((SdkException) t.getCause());
} Try / catch
try {
startIngestion();
} catch (RuntimeException e) {
if (e.getCause() instanceof SdkException) {
LOG.error("AWS SDK error code=%s", ((SdkException) e.getCause()).errorCode());
}
throw e;
} Prevention
- Rotate/renew AWS credentials before expiry and validate them at startup
- Confirm IAM policy allows GetRecords/GetShardIterator for the whole task lifetime
- Ensure the stream is not deleted while tasks run; use retention/monitoring
- Extend AWSClientUtil's recoverable list if your environment produces transient codes marked unrecoverable
When it happens
Trigger: scheduleBackgroundFetch -> fetchRecords calls getRecords and the AWS SDK throws a non-recoverable SdkClientException/SdkException (e.g. credentials failure, permission denied, malformed request).
Common situations: Expired or missing AWS credentials; IAM policy revocation mid-task; stream deleted while task is running; proxy/endpoint misconfiguration making every request fail deterministically.
Related errors
- StreamException
- can't reschedule fetch records runnable, recordsResult is nu
- getPosition() is not supported in Kinesis
- Partition [%s] has not been assigned
- Invalid operation - KinesisRecordSupplier has already been c
AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07).
Data as JSON: /api/errors/0f336edeaa8c2e2f.
Report an issue: GitHub.