mochajs/mocha · error · MochaInstanceAlreadyRunningError
ERR_MOCHA_INSTANCE_ALREADY_RUNNING
ERR_MOCHA_INSTANCE_ALREADY_RUNNING
Error message
Cannot dispose while the mocha instance is still running tests.
What it means
dispose() permanently marks a Mocha instance as disposed and clears references to test/hook functions so the GC can reclaim closures. Calling it while a run is in progress would tear down state the active runner still needs, so Mocha throws when _state is RUNNING.
Source
Thrown at lib/mocha.cjs:622
* @public
* @see {@link Mocha#dispose}
* @param {boolean} cleanReferencesAfterRun
* @return {Mocha} this
* @chainable
*/
Mocha.prototype.cleanReferencesAfterRun = function (cleanReferencesAfterRun) {
this._cleanReferencesAfterRun = cleanReferencesAfterRun !== false;
return this;
};
/**
* Manually dispose this mocha instance. Mark this instance as `disposed` and unable to run more tests.
* It also removes function references to tests functions and hooks, so variables trapped in closures can be cleaned by the garbage collector.
* @public
*/
Mocha.prototype.dispose = function () {
if (this._state === mochaStates.RUNNING) {
throw createMochaInstanceAlreadyRunningError(
"Cannot dispose while the mocha instance is still running tests.",
);
}
this.unloadFiles();
this._previousRunner && this._previousRunner.dispose();
this.suite.dispose();
this._state = mochaStates.DISPOSED;
};
/**
* Displays full stack trace upon test failure.
*
* @public
* @see [CLI option](../#-full-trace)
* @param {boolean} [fullTrace=true] - Whether to print full stacktrace upon failure.
* @return {Mocha} this
* @chainable
*/View on GitHub (pinned to 6bcbee4fd9)
Solutions
- Await the run's completion (the promise/exit from run() or runAsync()) before calling dispose()
- Move dispose() into a shutdown/after-run path rather than a hook or in-flight callback
- Debounce/queue dispose calls so concurrent shutdown logic cannot dispose mid-run
Example fix
// before
mocha.runAsync(failures => {});
mocha.dispose(); // throws if run still in progress
// after
const runner = await mocha.runAsync(failures => {});
await runner;
mocha.dispose(); // safe after run completes Defensive patterns
Strategy: try-catch
Validate before calling
// only dispose after run finished
if (mocha._state !== 'running') {
mocha.dispose();
} Type guard
function isDisposalSafe(mocha) {
return mocha._state !== 'running';
} Try / catch
try {
mocha.dispose();
} catch (err) {
if (err.code === 'ERR_MOCHA_INSTANCE_ALREADY_RUNNING') {
await runPromise; // await completion then retry once
mocha.dispose();
} else {
throw err;
}
} Prevention
- Always await run()/runAsync() before dispose()
- Never call dispose() from hooks or reporters during a run
- Centralize shutdown logic in one after-run path
When it happens
Trigger: Calling mocha.dispose() while mocha.run() (or runAsync()) is still executing and _state === mochaStates.RUNNING.
Common situations: Async cleanup code (e.g. process exit handlers, test-file teardown, watch-mode shutdown) that disposes without awaiting run completion; disposing from a hook or reporter callback during the run.
Related errors
- ERR_MOCHA_INSTANCE_ALREADY_DISPOSED
- async skip; aborting execution
- ERR_MOCHA_INVALID_ARG_TYPE
- ERR_MOCHA_FATAL
- ERR_MOCHA_INVALID_ARG_TYPE
AI-assisted analysis of mochajs/mocha@6bcbee4fd9 (2026-09-01).
Data as JSON: /api/errors/c8f561ff1db82e3e.
Report an issue: GitHub.