From d790fd00a0d74dff54c24532b02ea319a5f4717d Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Thu, 12 Dec 2024 12:54:03 -0500 Subject: [PATCH] fix(cli-repl): improve debuggability of `mongosh not initialized yet`errors MONGOSH-1943 (#2299) These errors have historically been very hard to debug, so adding stack traces unconditionally will hopefully improve this situation in the long term. --- packages/cli-repl/src/mongosh-repl.spec.ts | 2 +- packages/cli-repl/src/mongosh-repl.ts | 10 +++++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/packages/cli-repl/src/mongosh-repl.spec.ts b/packages/cli-repl/src/mongosh-repl.spec.ts index 3be21871f..f5cac3853 100644 --- a/packages/cli-repl/src/mongosh-repl.spec.ts +++ b/packages/cli-repl/src/mongosh-repl.spec.ts @@ -121,7 +121,7 @@ describe('MongoshNodeRepl', function () { it('throws an error if internal methods are used too early', function () { expect(() => mongoshRepl.runtimeState()).to.throw( - 'Mongosh not initialized yet' + /mongosh not initialized yet\nCurrent trace/ ); }); diff --git a/packages/cli-repl/src/mongosh-repl.ts b/packages/cli-repl/src/mongosh-repl.ts index 8903db2ab..a977572c2 100644 --- a/packages/cli-repl/src/mongosh-repl.ts +++ b/packages/cli-repl/src/mongosh-repl.ts @@ -126,6 +126,7 @@ type Mutable = { */ class MongoshNodeRepl implements EvaluationListener { _runtimeState: MongoshRuntimeState | null; + closeTrace?: string; input: Readable; lineByLineInput: LineByLineInput; output: Writable; @@ -1028,7 +1029,13 @@ class MongoshNodeRepl implements EvaluationListener { */ runtimeState(): MongoshRuntimeState { if (this._runtimeState === null) { - throw new MongoshInternalError('Mongosh not initialized yet'); + // This error can be really hard to debug, so we always attach stack traces + // from both when .close() was called and when + throw new MongoshInternalError( + `mongosh not initialized yet\nCurrent trace: ${ + new Error().stack + }\nClose trace: ${this.closeTrace}\n` + ); } return this._runtimeState; } @@ -1043,6 +1050,7 @@ class MongoshNodeRepl implements EvaluationListener { const rs = this._runtimeState; if (rs) { this._runtimeState = null; + this.closeTrace = new Error().stack; rs.repl?.close(); await rs.instanceState.close(true); await new Promise((resolve) => this.output.write('', resolve));