fix(jest-circus): prevent crash when asyncError is undefined for non-Error throws#16003
Conversation
✅ Deploy Preview for jestjs ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
babel-jest
babel-plugin-jest-hoist
babel-preset-jest
create-jest
@jest/diff-sequences
expect
@jest/expect-utils
jest
jest-changed-files
jest-circus
jest-cli
jest-config
@jest/console
@jest/core
@jest/create-cache-key-function
jest-diff
jest-docblock
jest-each
@jest/environment
jest-environment-jsdom
@jest/environment-jsdom-abstract
jest-environment-node
@jest/expect
@jest/fake-timers
@jest/get-type
@jest/globals
jest-haste-map
jest-jasmine2
jest-leak-detector
jest-matcher-utils
jest-message-util
jest-mock
@jest/pattern
jest-phabricator
jest-regex-util
@jest/reporters
jest-resolve
jest-resolve-dependencies
jest-runner
jest-runtime
@jest/schemas
jest-snapshot
@jest/snapshot-utils
@jest/source-map
@jest/test-result
@jest/test-sequencer
@jest/transform
@jest/types
jest-util
jest-validate
jest-watcher
jest-worker
pretty-format
commit: |
|
Hi @alex-all3dp, I’ve implemented the fixes described for this issue. However, I’m running into some CI failures related to the new test I added and I’m not fully sure what’s going wrong there. Could you please take a look and let me know if I’m missing something in how the test should be structured? I tried to follow the existing patterns, but I might have overlooked something. Thanks! |
|
Hi @ashoknarayan, thanks for picking this up! The logic changes in formatNodeAssertErrors.ts and utils.ts look correct. The CI failures are all coming from the new test file. The import '../mocks/testUtils' resolves to a path that doesn't exist in the package, which causes a module-not-found error that takes down the whole shard (which is why unrelated tests in shard 2 are failing too). There are test helpers in jest-circus/src/tests/ that show how to run jest-in-jest style tests, those should point you in the right direction. Worth noting is that a synchronous throw { status: 403 } won't actually hit the crash path you're fixing. The asyncError is only undefined when the error comes in through an async channel like a done callback or an unhandled subscription, because that's the case where jest-circus never gets to capture the async stack. To cover the fix you'd need a test that replicates that pattern. One more thing from the original issue worth addressing: Circus.TestError types the second tuple element as Exception (non-optional), but at runtime it can be undefined. Fixing the type definition alongside the logic changes would be the complete fix. |
|
Hi @alex-all3dp, I’ve addressed the feedback and updated the PR.
All checks are now passing. Would appreciate it if you could take another look when you get a chance. Thanks! |
|
Hi @alex-all3dp, |
Looks like code coverage targets are not met? |
|
And thanks for reviewing @alex-all3dp 🙏 |
| datasource | package | from | to | | ---------- | ------- | ------ | ------ | | npm | jest | 30.3.0 | 30.4.0 | ## [v30.4.0](https://github.com/jestjs/jest/blob/HEAD/CHANGELOG.md#3040) ##### Features - `[babel-jest]` Support collecting coverage from `.mts`, `.cts` (and other) files ([#15994](jestjs/jest#15994)) - `[jest-circus, jest-cli, jest-config, jest-core, jest-jasmine2, jest-types]` Add `--collect-tests` flag to discover and list tests without executing them ([#16006](jestjs/jest#16006)) - `[jest-config, jest-runner, jest-worker]` Add `workerGracefulExitTimeout` config option to control how long workers are given to exit before being force-killed ([#15984](jestjs/jest#15984)) - `[jest-config]` Add support for `jest.config.mts` as a valid configuration file ([#16005](jestjs/jest#16005)) - `[jest-config, jest-core, jest-reporters, jest-runner]` `verbose` and `silent` can now be set per-project; the project-level value overrides the global value for that project's tests ([#16133](jestjs/jest#16133)) - `[@jest/fake-timers]` Accept `Temporal.Duration` in `jest.advanceTimersByTime()` and `jest.advanceTimersByTimeAsync()` ([#16128](jestjs/jest#16128)) - `[@jest/fake-timers]` Accept `Temporal.Instant` and `Temporal.ZonedDateTime` in `jest.setSystemTime()` and `useFakeTimers({now})` ([#16128](jestjs/jest#16128)) - `[@jest/fake-timers]` Support faking `Temporal.Now.*` ([#16131](jestjs/jest#16131)) - `[jest-mock]` Add `clearMocksOnScope(scope)` on `ModuleMocker` for clearing every mock function exposed on a scope object ([#16088](jestjs/jest#16088)) - `[jest-resolve]` Add `canResolveSync()` on `Resolver` so callers can detect when a user-configured resolver only exports an `async` hook ([#16064](jestjs/jest#16064)) - `[jest-runtime]` Use synchronous `evaluate()` for ES modules without top-level `await` on Node versions that support it (v24.9+), and prefer the synchronous transform path when a sync transformer is configured ([#16062](jestjs/jest#16062)) - `[jest-runtime]` Support `require()` of ES modules on Node v24.9+ ([#16074](jestjs/jest#16074)) - `[jest-runtime]` Validate TC39 import attributes (`with { type: 'json' }`) on ESM imports ([#16127](jestjs/jest#16127)) - `[@jest/transform]` Add `canTransformSync(filename)` on `ScriptTransformer` so callers can pick the sync vs async transform path ([#16062](jestjs/jest#16062)) - `[jest-util]` Add `isError` helper ([#16076](jestjs/jest#16076)) - `[pretty-format]` Support React 19 ([#16123](jestjs/jest#16123)) ##### Fixes - `[expect-utils]` Fix `toStrictEqual` failing on `structuredClone` results due to cross-realm constructor mismatch ([#15959](jestjs/jest#15959)) - `[@jest/expect-utils]` Prevent `toMatchObject`/subset matching from throwing when encountering exotic iterables ([#15952](jestjs/jest#15952)) - `[fake-timers]` Convert `Date` to milliseconds before passing to `@sinonjs/fake-timers` ([#16029](jestjs/jest#16029)) - `[jest]` Export `GlobalConfig` and `ProjectConfig` TypeScript types ([#16132](jestjs/jest#16132)) - `[jest-circus]` Prevent crash when `asyncError` is undefined for non-Error throws ([#16003](jestjs/jest#16003)) - `[jest-circus, jest-jasmine2]` Include `Error.cause` in JSON `failureMessages` output ([#15967](jestjs/jest#15967)) - `[jest-config]` Fix preset path resolution on Windows when the preset uses subpath `exports` ([#15961](jestjs/jest#15961)) - `[jest-config]` Allow `collectCoverage` and `coverageProvider` in project config without a validation warning ([#16132](jestjs/jest#16132)) - `[jest-config]` Project config validator now emits "is not supported in an individual project configuration" instead of "probably a typing mistake" for known global-only options ([#16132](jestjs/jest#16132)) - `[jest-environment-node]` Fix `--localstorage-file` warning on Node 25+ ([#16086](jestjs/jest#16086)) - `[jest-reporters]` Apply global coverage threshold to unmatched pattern files in addition to glob/path thresholds ([#16137](jestjs/jest#16137)) - `[jest-reporters, jest-runner, jest-runtime, jest-transform]` Fix coverage report not showing correct code coverage when using `projects` config option ([#16140](jestjs/jest#16140)) - `[jest-runtime]` Resolve `expect` and `@jest/expect` from the internal module registry so test-file imports share the same `JestAssertionError` as the global `expect` ([#16130](jestjs/jest#16130)) - `[jest-runtime]` Improve CJS-from-ESM interop: `__esModule`/Babel default unwrap, broader named-export coverage, and shared CJS singleton across importers ([#16050](jestjs/jest#16050)) - `[jest-runtime]` Load `.js` files with ESM syntax but no `"type":"module"` marker as native ESM ([#16050](jestjs/jest#16050)) - `[jest-runtime]` Extend the `.js`-with-ESM-syntax fallback to `require()` on Node v24.9+ - falls back to `require(esm)` when the CJS parser rejects ESM syntax ([#16078](jestjs/jest#16078)) - `[jest-runtime]` Fix deadlocks and double-evaluation in concurrent ESM and wasm imports ([#16050](jestjs/jest#16050)) - `[jest-runtime]` Fix error when `require()` is called after the Jest environment has been torn down ([#15951](jestjs/jest#15951)) - `[jest-runtime]` Fix missing error when `import()` is called after the Jest environment has been torn down ([#16080](jestjs/jest#16080)) - `[jest-runtime]` Fix virtual `unstable_mockModule` registrations not respected in ESM ([#16081](jestjs/jest#16081)) - `[jest-runtime]` Apply `moduleNameMapper` when resolving modules with `require.resolve()` and the `paths` option ([#16135](jestjs/jest#16135)) ##### Chore & Maintenance - `[@jest/fake-timers]` Upgrade `@sinonjs/fake-timers` ([#16139](jestjs/jest#16139)) - `[jest-runtime]` Use synchronous `linkRequests` / `instantiate` for ESM linking on Node v24.9+ ([#16063](jestjs/jest#16063))
| datasource | package | from | to | | ---------- | ------- | ------ | ------ | | npm | jest | 30.3.0 | 30.4.2 | ## [v30.4.2](https://github.com/jestjs/jest/blob/HEAD/CHANGELOG.md#3042) ##### Fixes - `[jest-runtime]` Fix named imports from CJS modules whose `module.exports` is a function with own-property exports ([#16150](jestjs/jest#16150)) ## [v30.4.1](https://github.com/jestjs/jest/blob/HEAD/CHANGELOG.md#3041) ##### Features - `[jest-config, jest-core, jest-runner, jest-schemas, jest-types]` Allow custom runner configuration options via tuple format `['runner-path', {options}]` ([#16141](jestjs/jest#16141)) ##### Fixes - `[jest-runtime]` Align CJS-from-ESM default export with Node: `module.exports` is always the ESM default, `__esModule` unwrapping is no longer applied ([#16143](jestjs/jest#16143)) ## [v30.4.0](https://github.com/jestjs/jest/blob/HEAD/CHANGELOG.md#3040) ##### Features - `[babel-jest]` Support collecting coverage from `.mts`, `.cts` (and other) files ([#15994](jestjs/jest#15994)) - `[jest-circus, jest-cli, jest-config, jest-core, jest-jasmine2, jest-types]` Add `--collect-tests` flag to discover and list tests without executing them ([#16006](jestjs/jest#16006)) - `[jest-config, jest-runner, jest-worker]` Add `workerGracefulExitTimeout` config option to control how long workers are given to exit before being force-killed ([#15984](jestjs/jest#15984)) - `[jest-config]` Add support for `jest.config.mts` as a valid configuration file ([#16005](jestjs/jest#16005)) - `[jest-config, jest-core, jest-reporters, jest-runner]` `verbose` and `silent` can now be set per-project; the project-level value overrides the global value for that project's tests ([#16133](jestjs/jest#16133)) - `[@jest/fake-timers]` Accept `Temporal.Duration` in `jest.advanceTimersByTime()` and `jest.advanceTimersByTimeAsync()` ([#16128](jestjs/jest#16128)) - `[@jest/fake-timers]` Accept `Temporal.Instant` and `Temporal.ZonedDateTime` in `jest.setSystemTime()` and `useFakeTimers({now})` ([#16128](jestjs/jest#16128)) - `[@jest/fake-timers]` Support faking `Temporal.Now.*` ([#16131](jestjs/jest#16131)) - `[jest-mock]` Add `clearMocksOnScope(scope)` on `ModuleMocker` for clearing every mock function exposed on a scope object ([#16088](jestjs/jest#16088)) - `[jest-resolve]` Add `canResolveSync()` on `Resolver` so callers can detect when a user-configured resolver only exports an `async` hook ([#16064](jestjs/jest#16064)) - `[jest-runtime]` Use synchronous `evaluate()` for ES modules without top-level `await` on Node versions that support it (v24.9+), and prefer the synchronous transform path when a sync transformer is configured ([#16062](jestjs/jest#16062)) - `[jest-runtime]` Support `require()` of ES modules on Node v24.9+ ([#16074](jestjs/jest#16074)) - `[jest-runtime]` Validate TC39 import attributes (`with { type: 'json' }`) on ESM imports ([#16127](jestjs/jest#16127)) - `[@jest/transform]` Add `canTransformSync(filename)` on `ScriptTransformer` so callers can pick the sync vs async transform path ([#16062](jestjs/jest#16062)) - `[jest-util]` Add `isError` helper ([#16076](jestjs/jest#16076)) - `[pretty-format]` Support React 19 ([#16123](jestjs/jest#16123)) ##### Fixes - `[expect-utils]` Fix `toStrictEqual` failing on `structuredClone` results due to cross-realm constructor mismatch ([#15959](jestjs/jest#15959)) - `[@jest/expect-utils]` Prevent `toMatchObject`/subset matching from throwing when encountering exotic iterables ([#15952](jestjs/jest#15952)) - `[fake-timers]` Convert `Date` to milliseconds before passing to `@sinonjs/fake-timers` ([#16029](jestjs/jest#16029)) - `[jest]` Export `GlobalConfig` and `ProjectConfig` TypeScript types ([#16132](jestjs/jest#16132)) - `[jest-circus]` Prevent crash when `asyncError` is undefined for non-Error throws ([#16003](jestjs/jest#16003)) - `[jest-circus, jest-jasmine2]` Include `Error.cause` in JSON `failureMessages` output ([#15967](jestjs/jest#15967)) - `[jest-config]` Fix preset path resolution on Windows when the preset uses subpath `exports` ([#15961](jestjs/jest#15961)) - `[jest-config]` Allow `collectCoverage` and `coverageProvider` in project config without a validation warning ([#16132](jestjs/jest#16132)) - `[jest-config]` Project config validator now emits "is not supported in an individual project configuration" instead of "probably a typing mistake" for known global-only options ([#16132](jestjs/jest#16132)) - `[jest-environment-node]` Fix `--localstorage-file` warning on Node 25+ ([#16086](jestjs/jest#16086)) - `[jest-reporters]` Apply global coverage threshold to unmatched pattern files in addition to glob/path thresholds ([#16137](jestjs/jest#16137)) - `[jest-reporters, jest-runner, jest-runtime, jest-transform]` Fix coverage report not showing correct code coverage when using `projects` config option ([#16140](jestjs/jest#16140)) - `[jest-runtime]` Resolve `expect` and `@jest/expect` from the internal module registry so test-file imports share the same `JestAssertionError` as the global `expect` ([#16130](jestjs/jest#16130)) - `[jest-runtime]` Improve CJS-from-ESM interop: `__esModule`/Babel default unwrap, broader named-export coverage, and shared CJS singleton across importers ([#16050](jestjs/jest#16050)) - `[jest-runtime]` Load `.js` files with ESM syntax but no `"type":"module"` marker as native ESM ([#16050](jestjs/jest#16050)) - `[jest-runtime]` Extend the `.js`-with-ESM-syntax fallback to `require()` on Node v24.9+ - falls back to `require(esm)` when the CJS parser rejects ESM syntax ([#16078](jestjs/jest#16078)) - `[jest-runtime]` Fix deadlocks and double-evaluation in concurrent ESM and wasm imports ([#16050](jestjs/jest#16050)) - `[jest-runtime]` Fix error when `require()` is called after the Jest environment has been torn down ([#15951](jestjs/jest#15951)) - `[jest-runtime]` Fix missing error when `import()` is called after the Jest environment has been torn down ([#16080](jestjs/jest#16080)) - `[jest-runtime]` Fix virtual `unstable_mockModule` registrations not respected in ESM ([#16081](jestjs/jest#16081)) - `[jest-runtime]` Apply `moduleNameMapper` when resolving modules with `require.resolve()` and the `paths` option ([#16135](jestjs/jest#16135)) ##### Chore & Maintenance - `[@jest/fake-timers]` Upgrade `@sinonjs/fake-timers` ([#16139](jestjs/jest#16139)) - `[jest-runtime]` Use synchronous `linkRequests` / `instantiate` for ESM linking on Node v24.9+ ([#16063](jestjs/jest#16063))
| datasource | package | from | to | | ---------- | ------- | ------ | ------ | | npm | jest | 30.3.0 | 30.4.2 | ## [v30.4.2](https://github.com/jestjs/jest/blob/HEAD/CHANGELOG.md#3042) ##### Fixes - `[jest-runtime]` Fix named imports from CJS modules whose `module.exports` is a function with own-property exports ([#16150](jestjs/jest#16150)) ## [v30.4.1](https://github.com/jestjs/jest/blob/HEAD/CHANGELOG.md#3041) ##### Features - `[jest-config, jest-core, jest-runner, jest-schemas, jest-types]` Allow custom runner configuration options via tuple format `['runner-path', {options}]` ([#16141](jestjs/jest#16141)) ##### Fixes - `[jest-runtime]` Align CJS-from-ESM default export with Node: `module.exports` is always the ESM default, `__esModule` unwrapping is no longer applied ([#16143](jestjs/jest#16143)) ## [v30.4.0](https://github.com/jestjs/jest/blob/HEAD/CHANGELOG.md#3040) ##### Features - `[babel-jest]` Support collecting coverage from `.mts`, `.cts` (and other) files ([#15994](jestjs/jest#15994)) - `[jest-circus, jest-cli, jest-config, jest-core, jest-jasmine2, jest-types]` Add `--collect-tests` flag to discover and list tests without executing them ([#16006](jestjs/jest#16006)) - `[jest-config, jest-runner, jest-worker]` Add `workerGracefulExitTimeout` config option to control how long workers are given to exit before being force-killed ([#15984](jestjs/jest#15984)) - `[jest-config]` Add support for `jest.config.mts` as a valid configuration file ([#16005](jestjs/jest#16005)) - `[jest-config, jest-core, jest-reporters, jest-runner]` `verbose` and `silent` can now be set per-project; the project-level value overrides the global value for that project's tests ([#16133](jestjs/jest#16133)) - `[@jest/fake-timers]` Accept `Temporal.Duration` in `jest.advanceTimersByTime()` and `jest.advanceTimersByTimeAsync()` ([#16128](jestjs/jest#16128)) - `[@jest/fake-timers]` Accept `Temporal.Instant` and `Temporal.ZonedDateTime` in `jest.setSystemTime()` and `useFakeTimers({now})` ([#16128](jestjs/jest#16128)) - `[@jest/fake-timers]` Support faking `Temporal.Now.*` ([#16131](jestjs/jest#16131)) - `[jest-mock]` Add `clearMocksOnScope(scope)` on `ModuleMocker` for clearing every mock function exposed on a scope object ([#16088](jestjs/jest#16088)) - `[jest-resolve]` Add `canResolveSync()` on `Resolver` so callers can detect when a user-configured resolver only exports an `async` hook ([#16064](jestjs/jest#16064)) - `[jest-runtime]` Use synchronous `evaluate()` for ES modules without top-level `await` on Node versions that support it (v24.9+), and prefer the synchronous transform path when a sync transformer is configured ([#16062](jestjs/jest#16062)) - `[jest-runtime]` Support `require()` of ES modules on Node v24.9+ ([#16074](jestjs/jest#16074)) - `[jest-runtime]` Validate TC39 import attributes (`with { type: 'json' }`) on ESM imports ([#16127](jestjs/jest#16127)) - `[@jest/transform]` Add `canTransformSync(filename)` on `ScriptTransformer` so callers can pick the sync vs async transform path ([#16062](jestjs/jest#16062)) - `[jest-util]` Add `isError` helper ([#16076](jestjs/jest#16076)) - `[pretty-format]` Support React 19 ([#16123](jestjs/jest#16123)) ##### Fixes - `[expect-utils]` Fix `toStrictEqual` failing on `structuredClone` results due to cross-realm constructor mismatch ([#15959](jestjs/jest#15959)) - `[@jest/expect-utils]` Prevent `toMatchObject`/subset matching from throwing when encountering exotic iterables ([#15952](jestjs/jest#15952)) - `[fake-timers]` Convert `Date` to milliseconds before passing to `@sinonjs/fake-timers` ([#16029](jestjs/jest#16029)) - `[jest]` Export `GlobalConfig` and `ProjectConfig` TypeScript types ([#16132](jestjs/jest#16132)) - `[jest-circus]` Prevent crash when `asyncError` is undefined for non-Error throws ([#16003](jestjs/jest#16003)) - `[jest-circus, jest-jasmine2]` Include `Error.cause` in JSON `failureMessages` output ([#15967](jestjs/jest#15967)) - `[jest-config]` Fix preset path resolution on Windows when the preset uses subpath `exports` ([#15961](jestjs/jest#15961)) - `[jest-config]` Allow `collectCoverage` and `coverageProvider` in project config without a validation warning ([#16132](jestjs/jest#16132)) - `[jest-config]` Project config validator now emits "is not supported in an individual project configuration" instead of "probably a typing mistake" for known global-only options ([#16132](jestjs/jest#16132)) - `[jest-environment-node]` Fix `--localstorage-file` warning on Node 25+ ([#16086](jestjs/jest#16086)) - `[jest-reporters]` Apply global coverage threshold to unmatched pattern files in addition to glob/path thresholds ([#16137](jestjs/jest#16137)) - `[jest-reporters, jest-runner, jest-runtime, jest-transform]` Fix coverage report not showing correct code coverage when using `projects` config option ([#16140](jestjs/jest#16140)) - `[jest-runtime]` Resolve `expect` and `@jest/expect` from the internal module registry so test-file imports share the same `JestAssertionError` as the global `expect` ([#16130](jestjs/jest#16130)) - `[jest-runtime]` Improve CJS-from-ESM interop: `__esModule`/Babel default unwrap, broader named-export coverage, and shared CJS singleton across importers ([#16050](jestjs/jest#16050)) - `[jest-runtime]` Load `.js` files with ESM syntax but no `"type":"module"` marker as native ESM ([#16050](jestjs/jest#16050)) - `[jest-runtime]` Extend the `.js`-with-ESM-syntax fallback to `require()` on Node v24.9+ - falls back to `require(esm)` when the CJS parser rejects ESM syntax ([#16078](jestjs/jest#16078)) - `[jest-runtime]` Fix deadlocks and double-evaluation in concurrent ESM and wasm imports ([#16050](jestjs/jest#16050)) - `[jest-runtime]` Fix error when `require()` is called after the Jest environment has been torn down ([#15951](jestjs/jest#15951)) - `[jest-runtime]` Fix missing error when `import()` is called after the Jest environment has been torn down ([#16080](jestjs/jest#16080)) - `[jest-runtime]` Fix virtual `unstable_mockModule` registrations not respected in ESM ([#16081](jestjs/jest#16081)) - `[jest-runtime]` Apply `moduleNameMapper` when resolving modules with `require.resolve()` and the `paths` option ([#16135](jestjs/jest#16135)) ##### Chore & Maintenance - `[@jest/fake-timers]` Upgrade `@sinonjs/fake-timers` ([#16139](jestjs/jest#16139)) - `[jest-runtime]` Use synchronous `linkRequests` / `instantiate` for ESM linking on Node v24.9+ ([#16063](jestjs/jest#16063))
Fixes #15996
Handled cases where asyncError can be undefined when a test throws a non-Error value.
This prevents jest-circus from crashing and ensures the error is reported properly.