vitest-dev/vitest · error · TypeError

You must provide a Promise to expect() when using .rejects…

Error message

You must provide a Promise to expect() when using .rejects, not '${typeof wrapper}'.

What it means

`.rejects` needs a thenable (a Promise). The code wraps `obj` (calling it if it is a function, for Jest compat) and checks `wrapper.then`; if it is not a function, the assertion cannot observe a rejection and throws a `TypeError`.

Solutions

  1. Ensure the subject returns a rejected Promise (`Promise.reject(err)` or `throw` inside an async function).
  2. If the value is not a promise, assert on it directly without `.rejects`.
  3. Use `await` correctly so the rejection is observable.

Example fix

// before
async function fail() { return 'oops' }
expect(fail()).rejects.toThrow()

// after
async function fail() { throw new Error('oops') }
expect(fail()).rejects.toThrow('oops')
Defensive patterns

Strategy: type-guard

Validate before calling

const wrapper = typeof obj === 'function' ? obj() : obj
if (!(wrapper && typeof wrapper.then === 'function')) {
  throw new Error('pass a Promise when using .rejects')
}

Type guard

const isPromise = (v: unknown): v is Promise<unknown> =>
  !!v && typeof (v as any).then === 'function'

Prevention

When it happens

Trigger: `expect(42).rejects...`, `expect(() => 42).rejects...`, or passing a non-promise to a `.rejects` assertion; the producer returned a value instead of rejecting.

Common situations: Function returns a value in the happy path when the test expected a throw; forgot to `throw` inside an async function so it resolved instead of rejected; passing a sync result to `.rejects`.

Related errors


AI-assisted analysis of vitest-dev/vitest@1fa9837ec2 (2026-08-11). Data as JSON: /api/errors/c7cb813cfb25e20a. Report an issue: GitHub.

Appendix: source

Thrown at packages/expect/src/jest-expect.ts:1164

  utils.addProperty(
    chai.Assertion.prototype,
    'rejects',
    function __VITEST_REJECTS__(this: any) {
      const error = new Error('rejects')
      utils.flag(this, 'promise', 'rejects')
      utils.flag(this, 'error', error)
      const test: Test = utils.flag(this, 'vitest-test')
      const obj = utils.flag(this, 'object')
      const wrapper = typeof obj === 'function' ? obj() : obj // for jest compat

      if (utils.flag(this, 'poll')) {
        throw new SyntaxError(
          `expect.poll() is not supported in combination with .rejects`,
        )
      }

      if (typeof wrapper?.then !== 'function') {
        throw new TypeError(
          `You must provide a Promise to expect() when using .rejects, not '${typeof wrapper}'.`,
        )
      }

      const proxy: any = new Proxy(this, {
        get: (target, key, receiver) => {
          const result = Reflect.get(target, key, receiver)

          if (typeof result !== 'function') {
            return result instanceof chai.Assertion ? proxy : result
          }

          return (...args: any[]) => {
            utils.flag(this, '_name', key)
            const promise = Promise.resolve(wrapper).then(
              (value: any) => {
                const _error = new AssertionError(
                  `promise resolved "${utils.inspect(

View on GitHub (pinned to 1fa9837ec2)