Skip to content

Can't catch unhandled errors/rejections since 3.0.8 #7940

@e7h4n

Description

@e7h4n

Describe the bug

Starting from version 3.0.8, Vitest added the worker type "test" for the judgment of unhandled exceptions. This behavior makes unhandled errors thrown after the test ends unable to be handled by the user.

Reproduction

https://stackblitz.com/edit/vitest-dev-vitest-gbszaxae?embed=1&file=test%2Funhandled.test.ts

// unhandled.test.ts
it('foo', () => {
  new Promise((resolve, reject) => {
    reject('error');
  });
});

// vitest.setup.ts
process.on('unhandledRejection', () => {});

Expected

In 3.0.7, exceptions thrown in this Promise can be silently ignored

https://stackblitz.com/edit/vitest-dev-vitest-gtefuuf9?embed=1&file=package.json

Image

Actual

In 3.0.8, Vitest cannot silently handle unhandled rejection

https://stackblitz.com/edit/vitest-dev-vitest-gbszaxae?embed=1&file=test%2Funhandled.test.ts

Image

System Info

System:
    OS: Linux 5.0 undefined
    CPU: (8) x64 Intel(R) Core(TM) i9-9880H CPU @ 2.30GHz
    Memory: 0 Bytes / 0 Bytes
    Shell: 1.0 - /bin/jsh
  Binaries:
    Node: 20.19.1 - /usr/local/bin/node
    Yarn: 1.22.19 - /usr/local/bin/yarn
    npm: 10.8.2 - /usr/local/bin/npm
    pnpm: 8.15.6 - /usr/local/bin/pnpm
  npmPackages:
    @vitest/ui: =3.0.8 => 3.0.8 
    vite: latest => 6.3.5 
    vitest: =3.0.8 => 3.0.8

Used Package Manager

pnpm

Validations

Attempts

I checked the executor code and found that the following line of code has been modified since version 3.0.8.

https://github.com/vitest-dev/vitest/pull/7564/files#diff-c49d7f13cf089b49c98c93fc496d9f17280b7d50142330a79d3b03cb5bd1bc06L62

Before this, the catchError function will check all unhandled errors to see if the user might want to handle them

function catchError(err: unknown, type: string, event: 'uncaughtException' | 'unhandledRejection') {
const worker = state()

// If an error occurs during the testing process
if (worker.current) {
  const listeners = process.listeners(event as 'uncaughtException')
  // If there are other listeners, assume they are handled by user code
  // One is Vitest's own listener
  if (listeners.length > 1) {
    return
  }
}

After this, the catchError function only performs this kind of check on worker of type test.

- if (worker.current) {
+ if (worker.current?.type === 'test') {

I think this line of code broke the behavior before version 3.0.7

Metadata

Metadata

Assignees

No one assigned

    Labels

    p3-minor-bugAn edge case that only affects very specific usage (priority)

    Type

    Projects

    Status

    Approved

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions