Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use of instanceof Causes Unexpected Behavior in defaultRetryDecider - Jest #4273

Closed
3 tasks done
mtp1376 opened this issue Dec 12, 2022 · 4 comments
Closed
3 tasks done
Assignees
Labels
bug This issue is a bug. closed-for-staleness p2 This is a standard priority issue response-requested Waiting on additional info and feedback. Will move to \"closing-soon\" in 7 days.

Comments

@mtp1376
Copy link

mtp1376 commented Dec 12, 2022

Checkboxes for prior research

Describe the bug

Jest has problems (+, +) with instanceof and therefore the following implementation for asSdkError will always fall back to the last line (AWS SDK error wrapper for ...) which causes all of the error.XXX properties to be removed (like error.name which will be subsequently needed).

export const asSdkError = (error: unknown): SdkError => {
if (error instanceof Error) return error;
if (error instanceof Object) return Object.assign(new Error(), error);
if (typeof error === "string") return new Error(error);
return new Error(`AWS SDK error wrapper for ${error}`);
};

The shouldRetry function uses the defaultRetryDecider:
if (this.shouldRetry(err as SdkError, attempts, maxAttempts)) {

return attempts < maxAttempts && this.retryDecider(error) && this.retryQuota.hasRetryTokens(error);

Because the defaultRetryDecider is calling functions that rely on error.name which is replaced by the earlier new Error therefore they don't work as expected:
export const defaultRetryDecider = (error: SdkError) => {
if (!error) {
return false;
}
return isRetryableByTrait(error) || isClockSkewError(error) || isThrottlingError(error) || isTransientError(error);
};

For example isTransientError is using error.name as follows:
export const isTransientError = (error: SdkError) =>
TRANSIENT_ERROR_CODES.includes(error.name) ||
NODEJS_TIMEOUT_ERROR_CODES.includes((error as { code?: string })?.code || "") ||
TRANSIENT_ERROR_STATUS_CODES.includes(error.$metadata?.httpStatusCode || 0);

SDK version number

latest

Which JavaScript Runtime is this issue in?

Node.js

Details of the browser/Node.js/ReactNative version

v18.11.0

Reproduction Steps

Use the following code and place a breakpoint on asSdkError first line to see the error is being wrapped (not because it's not a true error, but because instanceof call fails). The test is just created to cause an error to be thrown.

import { AWS } from '../../src/services/aws_macros';

jest.setTimeout(3000000);

describe('Jest-AWS Error Issue', () => {
  it('triggers AWS error to inspect', async () => {
    // use a debugger to inspect internal sdk error object
    const client = new AWS({
      credentials: {
        accessKeyId: process.env.AWS_ACCESS_KEY_ID!,
        secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY!,
      },
      region: 'us-east-1',
    });
    const results = await Promise.all(
      [...Array(100).keys()].map(async () => await client.s3Client.listBuckets({})),
    );
  });
});

Observed Behavior

Due to the failure of instanceof to act as it should, it's falling back to new Error line and therefore causing defaultRetryDecider to have unexpected behavior.

Expected Behavior

The instanceof should be replaced by something that works throughout different environments, and the defaultRetryDecider should be working.

Possible Solution

Use of (error as {name?: ...}).name? maybe fixes the issue and the instanceof is no longer needed.

Additional Information/Context

No response

@mtp1376 mtp1376 added bug This issue is a bug. needs-triage This issue or PR still needs to be triaged. labels Dec 12, 2022
@mtp1376 mtp1376 changed the title Use of instanceof Causes Unexpected Behavior in defaultRetryDecider Use of instanceof Causes Unexpected Behavior in defaultRetryDecider - Jest Dec 12, 2022
@kuhe kuhe self-assigned this Dec 14, 2022
@yenfryherrerafeliz yenfryherrerafeliz removed the needs-triage This issue or PR still needs to be triaged. label Dec 14, 2022
@mtp1376
Copy link
Author

mtp1376 commented Jan 8, 2023

Can use something like this to wrap the original error. This way people can create workarounds easily (because the original error isn't thrown away).
https://twitter.com/housecor/status/1608795552644476928

@RanVaknin RanVaknin added p2 This is a standard priority issue needs-review This issue/pr needs review from an internal developer. labels Feb 10, 2023
@yenfryherrerafeliz yenfryherrerafeliz added queued This issues is on the AWS team's backlog and removed needs-review This issue/pr needs review from an internal developer. labels May 10, 2023
@kuhe
Copy link
Contributor

kuhe commented Mar 14, 2024

is this still a problem?

we use jest for our tests. The default retry implementation has also changed since this was reported.

@kuhe kuhe added response-requested Waiting on additional info and feedback. Will move to \"closing-soon\" in 7 days. and removed queued This issues is on the AWS team's backlog labels Mar 14, 2024
Copy link

This issue has not received a response in 1 week. If you still think there is a problem, please leave a comment to avoid the issue from automatically closing.

@github-actions github-actions bot added closing-soon This issue will automatically close in 4 days unless further comments are made. closed-for-staleness and removed closing-soon This issue will automatically close in 4 days unless further comments are made. labels Mar 25, 2024
Copy link

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs and link to relevant comments in this thread.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Apr 13, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
bug This issue is a bug. closed-for-staleness p2 This is a standard priority issue response-requested Waiting on additional info and feedback. Will move to \"closing-soon\" in 7 days.
Projects
None yet
Development

No branches or pull requests

4 participants