Describe the bug
AdaptiveRetryStrategy.refreshRetryTokenForRetry in @smithy/util-retry@4.3.6 has a missing await on the inner standardRetryStrategy.refreshRetryTokenForRetry() call, causing unhandled promise rejections that crash the Node.js process under sustained throttling.
// @smithy/util-retry 4.3.6, util-retry index.js:299-304
async refreshRetryTokenForRetry(tokenToRenew, errorInfo) {
this.rateLimiter.updateClientSendingRate(errorInfo);
const token = this.standardRetryStrategy.refreshRetryTokenForRetry(tokenToRenew, errorInfo); // <-- missing await
await this.rateLimiter.getSendToken();
return token;
}
When retry capacity is drained under throttling, the inner call returns a rejected promise with "No retry token available". Execution then suspends on getSendToken() (which sleeps via setTimeout under throttling). Node reaches the end of the event-loop tick with an unhandled rejected promise before the caller's try/catch can attach a handler — crashing the process.
Reproduction
Minimal repro using the exact installed package version — a loop calling refreshRetryTokenForRetry with every call wrapped in try/catch:
- AdaptiveRetryStrategy: 5th refresh crashes the process. The
catch block never executes.
- StandardRetryStrategy: Same error is caught normally, process exits cleanly.
Stack trace (production)
Error: No retry token available
at StandardRetryStrategy.refreshRetryTokenForRetry (node_modules/@smithy/util-retry/dist-cjs/index.js:265:13)
at processTicksAndRejections (node:internal/process/task_queues)
This is an unhandledRejection — not an error propagating through any application call chain. The retry middleware's try/catch (middleware-retry index.js:313-322) never gets the chance to handle it because the promise rejects before return token attaches a handler.
Impact
- Production crash-loop across multiple environments (production, staging, UAT)
- Triggered by sustained
ThrottlingException responses from @aws-sdk/client-translate
- Only workaround: revert
retryMode from 'adaptive' to 'standard'
Versions
@aws-sdk/client-translate: 3.1039.0
@smithy/util-retry: 4.3.6
- Node.js: v20
- Runtime: NestJS application on EKS
Fix status
We understand the fix exists upstream in current @smithy/core (re-exported by @smithy/util-retry@4.4.x) where the await is added. Filing this because:
- Version 4.3.6 is still installable via current
@aws-sdk/* packages and causes silent production crashes
- "No retry token available" is an internal SDK signal that should never surface as an unhandled rejection
- No changelog entry or migration note warns about this behavior in adaptive retry mode
Describe the bug
AdaptiveRetryStrategy.refreshRetryTokenForRetryin@smithy/util-retry@4.3.6has a missingawaiton the innerstandardRetryStrategy.refreshRetryTokenForRetry()call, causing unhandled promise rejections that crash the Node.js process under sustained throttling.When retry capacity is drained under throttling, the inner call returns a rejected promise with "No retry token available". Execution then suspends on
getSendToken()(which sleeps viasetTimeoutunder throttling). Node reaches the end of the event-loop tick with an unhandled rejected promise before the caller'stry/catchcan attach a handler — crashing the process.Reproduction
Minimal repro using the exact installed package version — a loop calling
refreshRetryTokenForRetrywith every call wrapped intry/catch:catchblock never executes.Stack trace (production)
This is an
unhandledRejection— not an error propagating through any application call chain. The retry middleware'stry/catch(middleware-retry index.js:313-322) never gets the chance to handle it because the promise rejects beforereturn tokenattaches a handler.Impact
ThrottlingExceptionresponses from@aws-sdk/client-translateretryModefrom'adaptive'to'standard'Versions
@aws-sdk/client-translate: 3.1039.0@smithy/util-retry: 4.3.6Fix status
We understand the fix exists upstream in current
@smithy/core(re-exported by@smithy/util-retry@4.4.x) where theawaitis added. Filing this because:@aws-sdk/*packages and causes silent production crashes