# @typescript-eslint/prefer-promise-reject-errors

> Require an `Error` as the reason when a promise is rejected

A rejected promise turns into a `throw` at the `await`. If the reason is a string, the `catch` block gets a value with no stack trace and no `message`, and `error instanceof Error` is false.

The rule checks `Promise.reject(...)` and calls to `reject` inside `new Promise((resolve, reject) => ...)`. Rejecting with nothing is reported too.

This is `prefer-promise-reject-errors` with types. It looks at the reason's type, so a variable that holds a string is reported and a class that extends `Error` isn't.

With `bunfig.toml`, turning this rule on runs it in TypeScript files and `prefer-promise-reject-errors` in JavaScript files, so nothing is reported twice. With an ESLint config, turn the other rule off when you use this one.

`bun lint --type-aware` turns this rule on in TypeScript files.

{/* Generated by src/codegen/lint-rule-docs.ts. Do not edit this section. */}

## Configure

Off by default. This rule needs types, so turning it on makes `bun lint` type check your code first.

```toml bunfig.toml
[lint.rules]
"@typescript-eslint/prefer-promise-reject-errors" = "error" # or "warn"
```

Every option, set to its default:

```toml bunfig.toml
[lint.rules]
"@typescript-eslint/prefer-promise-reject-errors" = ["error", {
  allowEmptyReject = false,
  allowThrowingAny = false,
  allowThrowingUnknown = false,
  allow = [], # list of strings or objects
}]
```

{/* End of the generated section. */}

## Examples

Reported:

{/* bad {"count": 3} */}
```ts
function load(url: string, reason: string) {
  if (!url) return Promise.reject("missing url");
  if (url === "/") return Promise.reject();

  return new Promise((resolve, reject) => {
    reject(reason);
  });
}
```

Not reported:

{/* good */}
```ts
class HttpError extends Error {}

function load(url: string) {
  if (!url) return Promise.reject(new Error("missing url"));

  return new Promise((resolve, reject) => {
    reject(new HttpError("not found"));
  });
}
```

## Options

| Option | Default | What it does |
| --- | --- | --- |
| `allowEmptyReject` | `false` | Allow `Promise.reject()` and `reject()` without a reason. |
| `allowThrowingAny` | `false` | Allow a reason of type `any`. |
| `allowThrowingUnknown` | `false` | Allow a reason of type `unknown`. |
| `allow` | `[]` | Other types that are allowed as a reason. |

With `strict`, the value in a `catch` block is `unknown`, so passing it on is reported:

{/* bad */}
```ts
async function retry(task: () => Promise<void>) {
  try {
    await task();
  } catch (error) {
    return Promise.reject(error);
  }
}
```

With `allowThrowingUnknown: true` it's allowed:

{/* good {"options": [{"allowThrowingUnknown": true}]} */}
```ts
async function retry(task: () => Promise<void>) {
  try {
    await task();
  } catch (error) {
    return Promise.reject(error);
  }
}
```

Each `allow` entry is a type name, or an object that also says where the type comes from: `{ "from": "file", "name": "Failure" }`, `{ "from": "lib", "name": "Date" }`, or `{ "from": "package", "name": "Failure", "package": "some-package" }`. With the first of these, this is allowed:

{/* good {"options": [{"allow": [{"from": "file", "name": "Failure"}]}]} */}
```ts
interface Failure {
  code: number;
}

function fail(failure: Failure) {
  return Promise.reject(failure);
}
```
