Skip to content

Bug: Missing await in AdaptiveRetryStrategy causes unhandled promise rejection crash (@smithy/util-retry 4.3.6) #8096

Description

@Osama-Yusuf

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:

  1. Version 4.3.6 is still installable via current @aws-sdk/* packages and causes silent production crashes
  2. "No retry token available" is an internal SDK signal that should never surface as an unhandled rejection
  3. No changelog entry or migration note warns about this behavior in adaptive retry mode

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions