jest: --detectOpenHandles prints nothing, just hangs

šŸ› Bug Report

When I run my test suite I get one of these 2 messages:

A worker process has failed to exit gracefully and has been force exited. This is likely caused by tests leaking due to improper teardown. Try running with --runInBand --detectOpenHandles to find leaks.

or

Jest did not exit one second after the test run has completed. This usually means that there are asynchronous operations that werenā€™t stopped in your tests. Consider running Jest with --detectOpenHandles to troubleshoot this issue.

For one, I think the mention of --runInBand in the first message is probably not necessary. But in any case, when I start running jest with --detectOpenHandles, I get no output, jest just hangs after finishing the tests.

Expected behavior

I would expect detectOpenHandles to give me actionable output.

envinfo

$ npx envinfo --preset jest
npx: installed 1 in 1.775s

  System:
    OS: macOS 10.15.2
    CPU: (4) x64 Intel(R) Core(TM) i7-7660U CPU @ 2.50GHz
  Binaries:
    Node: 10.18.0 - ~/.nvm/versions/node/v10.18.0/bin/node
    Yarn: 1.21.1 - /usr/local/bin/yarn
    npm: 6.13.6 - ~/.nvm/versions/node/v10.18.0/bin/npm
  npmPackages:
    jest: ^25.1.0 => 25.1.0

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Reactions: 147
  • Comments: 54 (5 by maintainers)

Commits related to this issue

Most upvoted comments

Iā€™m seeing the same issue. Iā€™m not asking for help debugging my code, Iā€™m pointing out a ā€œconcrete problem in jestā€. In some code bases, when running jest with --runInBand --detectOpenHandles, as recommended by the CLI, the tests complete with no reported issues and jest hangs.

I have not been able to isolate a minimal reproduction, but this does not mean the issue isnā€™t real. Unless this is expected behavior, please reopen in acknowledgement that this is clearly affecting users.

this solves it ā€œtestā€: ā€œjest --watch --runInBand --detectOpenHandlesā€

@jeysal hello. Please check my repo - umbress. You can find all my tests and configs in there. Also you can go to pull requests tab and see there an ongoing/failed tests for my latest PR - full GitHub Actions logs is there for you to explore šŸ˜ƒ

In my PC when I start npm test it says

A worker process has failed to exit gracefully and has been force exited. This is likely caused by tests leaking due to improper teardown. Try running with --runInBand --detectOpenHandles to find leaks.

But in Github Actions message is changing to

Jest did not exit one second after the test run has completed.

Edit: --forceExit and --detectOpenHandles has fixed this issue for me, but once again it feels like Iā€™m fighting with only symptoms.

@Prestaul donā€™t bother. They rather ask you to provide minimal repro than actually try to investigate after a bunch of complaints.

@laurent22 is exactly right. This thread is not about posting workarounds, which is what this has become. Nothing against everyone sharing info. Without any official response that is actually useful, thatā€™s what happens.

Given that thereā€™s clearly no intention to fix this, I guess itā€™s time for me to unsubscribe from my own bug report. Sigh.

Why does the library have --detectOpenHandles if you have to install another library to detect the open handles?

Of course you also can find the leaked handles manually by isolating the leaking component, but this does not change the fact that --detectOpenHandles is broken and this ticket should be re-opened.

confirmed. I saw the same message in the console, ran the command with --runInBand and --detectOpenHandles but it was left hanging

same version of mac os, node 12.13.0, yarn 1.21.1, npm 6.13.6, jest 25.1.0

jest --forceExit --detectOpenHandles this solves the problem for me

What is expected behaviour of --detectOpenHandles? The documentation says that it shall print something. But when I run JEST with this parameter, the test never finishes and there is nothing written at all when I kill the process with Ctrl-C. Am I missing something?

I have the same issue. npm test leads to

Jest did not exit one second after the test run has completed.

This usually means that there are asynchronous operations that weren't stopped in your tests. Consider running Jest with `--detectOpenHandles` to troubleshoot this issue.

Then npm test -- --detectOpenHandles leads to no errors but a slow test run and probably due to a force quit of jest after some timeout

Then npm test -- --forceExit leads to the message

Force exiting Jest: Have you considered using `--detectOpenHandles` to detect async operations that kept running after all tests finished?

So executing npm test -- --forceExit --detectOpenHandles leads to no warning and messages and a quick end of the test process.

This makes sense but I would rather like to know which handle of mine is still open to close it in a clean way. So I say this is a bug and should be reopened.

Edit 2020-04-23:

I was able to strip down my project and reproduce the error. Have an assumption what is the reason in my code which causes the issue. If this assumption turns out to be true I will link a repo here to reproduce it which might help the Jest devs to debug the issue.

Edit 2020-04-24:

Registered timeouts are not detected by the jest ā€œdetectOpenHandlesā€ option Here a repo to reproduce the issue and a fix on client side https://github.com/TarSzator/jest-open-handle-test

I hope it helps to find the error in Jest or Jest is intended like that then it might help users to find and fix issues on their side.

Iā€™ve also hit this a number of times and again today, so I made a minimal repro from my most recent encounter:

https://github.com/levilansing/jest-9473

Iā€™m reasonably certain Iā€™ve encountered this with timers and promises in the past, but couldnā€™t repro just now. In this repo, Iā€™ve left a connection open to redis during tests, which should obviously be mocked during tests, but demonstrates that jest does not provide any hint to what might be causing the tests to hang when using --detectOpenHandles in this case.

Without a repro, this is not actionable. Feel free to reopen if you can provide a minimal (= not just a project with lots of tests and config that may or may not be related to the issue) one.

For one, I think the mention of --runInBand in the first message is probably not necessary.

--detectOpenHandles without --runInBand does not really make sense (unless your tests are already being run in band anyway), since you will be detecting open handles in the main process, while your tests are running in child processes. We should amend all messages mentioning --detectOpenHandles to also include --runInBand, Iā€™ve noted to do that at some point.

Adding leaked-handles package to my Jest setup code and then --runInBand allowed to find which test suit is leaking.

in my case it was my unclosed database connections that was triggering this logā€¦

The problem is not really what triggers this log, as that varies from user to user. The problem is that --detectOpenHandles makes Jest freezes instead of printing information.

Shouldnā€™t this issue be re-opened, now that someone has provided a minimal repro?

We see this problem after updating to jest 26.6.0 and did not see it before that version.

For anyone still struggling with this, I managed to narrow down my issue by using a combination of suggestions above. Hereā€™s what I did:

  1. Ran npx jest --runInBand --detectOpenHandles src/tests to validate that something was indeed hanging
  2. Ran npx jest --runInBand --detectOpenHandles src/tests/someDir on several dirs to figure out which one was the culprit (if it doesnā€™t hang and exits cleanly, move on to another dir)
  3. Ran npx jest --runInBand --detectOpenHandles src/tests/someDir/someFile to figure out exactly which file was causing the problem
  4. Commented out tests within the file to figure out exactly which test(s) were causing the problem

For anyone using NEXT.js, this line was the problem for me: const nextApp = next({ dev: process.env.NODE_ENV !== 'production' });. Iā€™m ripping it out tomorrow and migrating to serving an app directly from Express šŸ˜¬

Hope this helps someone else out there!

For anyone struggling with this issue and using ioredis package: A simple fix would be to quit the redis connection in your afterEach or afterAll hooks:

// src/lib/redisClient.js # whatever path you instantiate the package
export const redis = new Redis(config.REDIS_URL);
import { redis } from "src/lib/redisClient";

// tests/setupTest.js
afterAll(async () => {
    await redis.quit();
});

Referring from: https://github.com/luin/ioredis/issues/1088#issuecomment-732490888

Hi, I am facing the similar issue. I just write this simple test.

describe('first test', () => {
  it('demo test', () => {
    expect(true).toEqual(true);  
  });
});

But jest is not returning to the terminal after running the test. --detectOpenHandles is also not showing any output.

I had same issue but I noticed that it works fine when I specify a path when running my tests

Jest outputs correctly open handles: jest --runInBand --detectOpenHandles src/ Where here I get nothing: jest --runInBand --detectOpenHandles

EDIT: I think it might be connected to #10777

This was the issue for meā€¦ I applied the workaround suggested in that issue to get jest to exit again.

I am seeing these errors too (even after .skip) all of my tests. However, When adding both --forceExit --detectOpenHandles, the test exists ā€œcleanlyā€ (no warnings). I suspect there is a red herring somewhere that is causing this since I could not find any leaks in my tests (although they may exist). Iā€™m not of the opinion that the combination of those flags listed is a real fix, but the tests did exit properly and without warnings or errors.

Iā€™ve also hit this a number of times and again today, so I made a minimal repro from my most recent encounter:

levilansing/jest-9473

Iā€™m reasonably certain Iā€™ve encountered this with timers and promises in the past, but couldnā€™t repro just now. In this repo, Iā€™ve left a connection open to redis during tests, which should obviously be mocked during tests, but demonstrates that jest does not provide any hint to what might be causing the tests to hang when using --detectOpenHandles in this case.

Using jest@next detects 2 handles:

image

stack trace of the first one isnā€™t suuuuper useful, but itā€™s something pointing to redis at least šŸ™‚

Edit 2020-04-24:

Registered timeouts are not detected by the jest ā€œdetectOpenHandlesā€ option Here a repo to reproduce the issue and a fix on client side TarSzator/jest-open-handle-test

I hope it helps to find the error in Jest or Jest is intended like that then it might help users to find and fix issues on their side.

Same here

image


As far as I can see, these are the only 2 reproductions posted, which have both been fixed (in #11429 šŸš€), so Iā€™ll close this one as itā€™s suuuuper long and full of workarounds and "+1"s.

One improvement I want to make is print ā€œsorry, we found no open handlesā€ or some such so it doesnā€™t seems like Jest didnā€™t react to the flag.


If somebody using Jest 27 or newer (try out jest@next, stable will come next week) still have this issue, please open up a new one with a minimal reproduction (like the two I checked here).

FWIW, I have this same issue on Linux which isnā€™t installing fsevents at all.

None of the previous instructions helped me, I still get it hanging. Here is a work-around that worked for me:

Install why-is-node-running: npm i why-is-node-running Edit jest entry point to use it, in my case the file is located in./node_modules/.bin/jest

I made it to look exactly like this:

#!/usr/bin/env node
/**
 * Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

const log = require('why-is-node-running') // should be your first require

setInterval(function () {
  console.log('WILL PRINT ACTIVE HANDLES');
  log() // logs out active handles that are keeping node running
}, 1000)


const importLocal = require('import-local');

if (!importLocal(__filename)) {
  require('jest-cli/bin/jest');
}

Then running jest: ./node_modules/.bin/jest (my params) --runInBand Got it printing some helpful information every 1 second.


Jest code says it is based on why-is-node-running: https://github.com/facebook/jest/blob/1cc205c274defb24f8b827b8a0c53c161c79d106/packages/jest-core/src/collectHandles.ts#L38

In my case there was a setInterval, and clear interval in a react component

For example -

export default function App() {
  const [label, setLabel] = useState(Math.random());
  useEffect(() => {
    const interval = setInterval(() => {
      setLabel(Math.random());
    }, 1000);
    return () => {
      clearInterval(interval);
    };
  }, []);

  return (
    <div className="App">
      <h1>{label}</h1>
    </div>
  );
}

I used jest.useFakeTimers(); on the test https://jestjs.io/docs/en/timer-mocks.html and it was fixed

But the original problem --detectOpenHandles should be fixed

@lmajowka @papaiatis refer to comment and install the proposed module. For me it was Redis module that was not properly closing the connection. In your environment it will show you some other leaking pipes.

Yes, I tried that, and it didnā€™t give me any valuable information. But after all I figured out the root cause of my issue: I was using TypeORM to manage a DB and I had to explicitly close the connection to the DB.

For anyone struggling with this issue and using ioredis package: A simple fix would be to quit the redis connection in your afterEach or afterAll hooks:

// src/lib/redisClient.js # whatever path you instantiate the package
export const redis = new Redis(config.REDIS_URL);
import { redis } from "src/lib/redisClient";

// tests/setupTest.js
afterAll(async () => {
    await redis.quit();
});

Referring from: luin/ioredis#1088 (comment)

I have experienced the same problem with a ioredis using test, solved as proposed. It looks like the test process hangs with the redis open connection

I had a similar issue to @Jule-, but it was how I was making a connection to Mongo via mongoose. It seems like mongooseā€™s mongoose.connection.close() in a top-level afterAll within a setupTests file isnā€™t consistently closing the connection.

My approach was to set up a single connection before all tests within a setupTests.ts file to register mongoose models, then close the single connection after all test suites have finished. This appears to cause issues with Jest.

For example: database/index.ts

const options = {
  useNewUrlParser: true, // avoids DeprecationWarning: current URL string parser is deprecated
  useCreateIndex: true, // avoids DeprecationWarning: collection.ensureIndex is deprecated.
  useFindAndModify: false, // avoids DeprecationWarning: collection.findAndModify is deprecated.
  useUnifiedTopology: true // avoids DeprecationWarning: current Server Discovery and Monitoring engine is deprecated
};

export const connectToDatabase = (): Promise<typeof mongoose> =>
  mongoose.connect(`mongodb://localhost/${DATABASE}`, options);

setupTests.ts (this works about 50% of the time unless I used --runInBand, then it worked fine)

import mongoose from "mongoose";
import { connectToDatabase } from "~database";

beforeAll(async () => {
  await connectToDatabase();
});

afterAll(() => {
  mongoose.connection.close();
});

Instead, removing the setupTests.ts file and moving the connection within each test suite seems to have fixed the warning:

 import mongoose from "mongoose";
 import { connectToDatabase } from "~database";

 describe("Example", () => {
   beforeAll(async () => {
     await connectToDatabase();
   });

   afterAll(async () => {
     await mongoose.connection.close();
   });

   it("...", () => {});
 });

Same here.

envInfo:

 System:
    OS: macOS 10.15.7
    CPU: (4) x64 Intel(R) Core(TM) i5-7360U CPU @ 2.30GHz
  Binaries:
    Node: 12.18.3 - ~/.nvm/versions/node/v12.18.3/bin/node
    npm: 6.14.8 - ~/.nvm/versions/node/v12.18.3/bin/npm
  npmPackages:
    jest: 26.6.3 => 26.6.3 

Jest cmd: jest --testTimeout=20000 --runInBand --detectOpenHandles

Code example:

describe('Plugin', () => {
    test('should launch browser', async () => {
        await new Promise((resolve) => setTimeout(() => resolve(), 5000));
    });
});

Process hangs. No open handles are logged.

EDIT: I think it might be connected to https://github.com/facebook/jest/issues/10777

Hello all. My issue is that running jest produces the ā€œa worker process failed to exit gracefullyā€ but when i try to isolate with the provided CLI args --runInBand and --detectOpenHandles, I am no longer able to produce the error. soā€¦ just wanted to throw that out there. i also found this open issue in testing-library:

https://github.com/testing-library/dom-testing-library/issues/524

not sure itā€™s related, but itā€™s something.

I havenā€™t had a chance to take a closer look at any of the comments/repros posted yet, but yeah can reopen even though not sure whether I can look at it myself

Same problem here, but I am just starting a new project. Should I check other test libraries? any suggestion? thanks

Iā€™m having the same problem. Tried all suggestions here but to no avail. @jeysal are you willing to re-open now since a minimal repro is provided?

I come here to share my experience.

TL;DR: in my case it was my unclosed database connections that was triggering this logā€¦

Long version: I use Jest to run backend tests, so in my tests I use supertest which starts my express app which starts MongoDB connections with mongooseā€¦ And obviously after my tests are finished, I did not close my connections, pretty far from my thoughts when I firstly saw this issueā€¦ Then for me this is what fixed my issue:

afterAll(async () => {
  for (const connection of mongoose.connections) {
    await connection.close();
  }
});

In order to reproduce:

import request from "supertest";
import app from "./app";
/**
 * app:
 * - an express() app instance
 * - with an endpoint `/api/test` for example
 * - which requires a mongoose Model with an active connection
 */

describe('description', () => {
  it('description', async () => {
    const req = await request(app).post("/api/test");
  })
});

HTH

Hi All, Iā€™m having a similar issue, but only when collecting coverage. All tests runs fine without the --collectCoverage at the moment I turn this flag on, I start getting some weird issues, including the 2 messages stated on the bug report.

@jeysal Hi, I can see above that two minimal repros were provided. Is it possible to reopen this?

Thanks!