{"record":{"id":"0f336edeaa8c2e2f","repo":"apache/druid","slug":"runtimeexception","errorCode":null,"errorMessage":"RuntimeException","messagePattern":"RuntimeException","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"extensions-core/kinesis-indexing-service/src/main/java/org/apache/druid/indexing/kinesis/KinesisRecordSupplier.java","lineNumber":366,"sourceCode":"          if (recordsResult != null) {\n            shardIterator = recordsResult.nextShardIterator(); // will be null if the shard has been closed\n            scheduleBackgroundFetch(fetchDelayMillis);\n          } else {\n            throw new ISE(\"can't reschedule fetch records runnable, recordsResult is null??\");\n          }\n        }\n        catch (ResourceNotFoundException | InvalidArgumentException e) {\n          // aws errors\n          log.error(e, \"encounted AWS error while attempting to fetch records, will not retry\");\n          throw e;\n        }\n        catch (SdkException e) {\n          if (AWSClientUtil.isClientExceptionRecoverable(e)) {\n            log.warn(e, \"encounted unknown recoverable AWS exception, retrying in [%,dms]\", EXCEPTION_RETRY_DELAY_MS);\n            scheduleBackgroundFetch(EXCEPTION_RETRY_DELAY_MS);\n          } else {\n            log.warn(e, \"encounted unknown unrecoverable AWS exception, will not retry\");\n            throw new RuntimeException(e);\n          }\n        }\n        catch (Throwable e) {\n          // non transient errors\n          log.error(e, \"unknown fetchRecords exception, will not retry\");\n          throw new RuntimeException(e);\n        }\n\n      };\n    }\n\n    private void seek(ShardIteratorType iteratorEnum, String sequenceNumber)\n    {\n      log.debug(\n          \"Seeking partition [%s] to [%s]\",\n          streamPartition.getPartitionId(),\n          sequenceNumber != null ? sequenceNumber : iteratorEnum.toString()\n      );","sourceCodeStart":348,"sourceCodeEnd":384,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/extensions-core/kinesis-indexing-service/src/main/java/org/apache/druid/indexing/kinesis/KinesisRecordSupplier.java#L348-L384","documentation":"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.","triggerScenarios":"scheduleBackgroundFetch -> fetchRecords calls getRecords and the AWS SDK throws a non-recoverable SdkClientException/SdkException (e.g. credentials failure, permission denied, malformed request).","commonSituations":"Expired or missing AWS credentials; IAM policy revocation mid-task; stream deleted while task is running; proxy/endpoint misconfiguration making every request fail deterministically.","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"],"exampleFix":"// before\nthrow new RuntimeException(e);\n// after\nif (e.errorCode().equals(\"ThrottlingException\")) {\n  scheduleBackgroundFetch(EXCEPTION_RETRY_DELAY_MS);\n} else {\n  throw new RuntimeException(e);\n}","handlingStrategy":"retry","validationCode":"// verify credentials and stream exist before consuming\nGetRecordsPermissionCheck: kinesisClient.describeStreamSummary(DescribeStreamRequest.builder().streamName(stream).build());","typeGuard":"static boolean unrecoverableSdkError(Throwable t) {\n  return t instanceof RuntimeException && t.getCause() instanceof SdkException\n      && !AWSClientUtil.isClientExceptionRecoverable((SdkException) t.getCause());\n}","tryCatchPattern":"try {\n  startIngestion();\n} catch (RuntimeException e) {\n  if (e.getCause() instanceof SdkException) {\n    LOG.error(\"AWS SDK error code=%s\", ((SdkException) e.getCause()).errorCode());\n  }\n  throw e;\n}","preventionTips":["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"],"tags":["kinesis","aws-sdk","unrecoverable-error"],"backgroundTag":"api-error-response","analyzedSha":"9b90983fd291f26935af934383ce360473179e4d","analyzedAt":"2026-09-07T13:32:30.957Z","contentChangedAt":"2026-09-07T13:32:30.957Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}