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

Non-extensible rejections result in unhandled rejection #25

Open
openreply-dleinhaeuser opened this issue May 13, 2019 · 2 comments
Open

Comments

@openreply-dleinhaeuser
Copy link

If the input function somehow rejects with a non-object, decorateErrorWithCounts will throw an error which leads to an unhandled rejection.

Example:

const pRetry = require('./');

pRetry(() => Promise.reject(Object.preventExtensions(new Error())))
    .catch(console.error);

Expected result:
The retry handler treats the non-extendable like any other (minus the decorating of course).

Actual result:
An UnhandledPromiseRejectionWarning is generated, the code continues on neither the resolution nor the rejection path.

Generally the code seems to not be well defended against errors from unexpected sources. For example. throwing from the onFailedAttempt function would also result in an unhandled rejection.

@openreply-dleinhaeuser openreply-dleinhaeuser changed the title Non-object rejections result in unhandled rejection Non-extensible rejections result in unhandled rejection May 13, 2019
@schmiegelt
Copy link

As I had the same issue, I solved it by wrapping the actual function call in an own function. In there, the non-extendable error can be cought and replaced by an extendable one.

So, instead of

const response = await doSomething()

I created a new function

async function trySomething() {
    try {
        await doSomething()
        return "Success"
    }
    catch(e) {
        //console.log(e)
        throw(new Error("Could not do something"))
    }
}

and used this in the p-reply code

const run = async () => {
	const response = await trySomething()

	return response
};

airhorns added a commit to gadget-inc/p-retry that referenced this issue Nov 16, 2024
Before this change, `pRetry` blindly tries to modify the error thrown by the inner function. If that error happens to not be an extensible object, this modification itself throws, which obscures the inner error. This change makes `pRetry` not add these properties if the error object can't be extended under the presumption that retrying this error is better than hard erroring the first time its thrown.

Fixes sindresorhus#25
@marchuffnagle
Copy link

This seems like a tricky one to fix in p-retry without making a breaking change. p-retry itself doesn't appear to read the two properties set on the error (attemptNumber and retriesLeft), but it does specify that they'll be available in the error passed to onFailedAttempt and shouldRetry.

Short of making a breaking change, should the documentation be updated to say, "if your function to be retried throws something that can't be extended, this is going to get weird"? I can't imagine this happens that often, but it's certainly more than zero.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants