diff --git a/doc/api/errors.md b/doc/api/errors.md
index 71671c33be47f0..813bef36d53a04 100644
--- a/doc/api/errors.md
+++ b/doc/api/errors.md
@@ -2573,6 +2573,12 @@ disconnected socket.
A call was made and the UDP subsystem was not running.
+
+
+### `ERR_SOURCE_MAP_CANNOT_PARSE`
+
+The source map could not be parsed because it is not valid JSON.
+
### `ERR_SOURCE_MAP_MISSING_SOURCE`
diff --git a/lib/internal/errors.js b/lib/internal/errors.js
index a3275c4bcb50ac..0c16c29a64d849 100644
--- a/lib/internal/errors.js
+++ b/lib/internal/errors.js
@@ -1704,6 +1704,7 @@ E('ERR_SOCKET_CONNECTION_TIMEOUT',
E('ERR_SOCKET_DGRAM_IS_CONNECTED', 'Already connected', Error);
E('ERR_SOCKET_DGRAM_NOT_CONNECTED', 'Not connected', Error);
E('ERR_SOCKET_DGRAM_NOT_RUNNING', 'Not running', Error);
+E('ERR_SOURCE_MAP_CANNOT_PARSE', `The source map for '%s' does not exist or is not valid JSON.`, Error);
E('ERR_SOURCE_MAP_MISSING_SOURCE', `Cannot find '%s' imported from the source map for '%s'`, Error);
E('ERR_SRI_PARSE',
'Subresource Integrity string %j had an unexpected %j at position %d',
diff --git a/lib/internal/test_runner/coverage.js b/lib/internal/test_runner/coverage.js
index 1b5ba7912dcb7d..a2f728b825da11 100644
--- a/lib/internal/test_runner/coverage.js
+++ b/lib/internal/test_runner/coverage.js
@@ -32,6 +32,7 @@ const { fileURLToPath } = require('internal/url');
const { kMappings, SourceMap } = require('internal/source_map/source_map');
const {
codes: {
+ ERR_SOURCE_MAP_CANNOT_PARSE,
ERR_SOURCE_MAP_MISSING_SOURCE,
},
} = require('internal/errors');
@@ -353,6 +354,7 @@ class TestCoverage {
continue;
}
const { data, lineLengths } = sourceMapCache[url];
+ if (!data) throw new ERR_SOURCE_MAP_CANNOT_PARSE(url);
let offset = 0;
const executedLines = ArrayPrototypeMap(lineLengths, (length, i) => {
const coverageLine = new CoverageLine(i + 1, offset, null, length + 1);
diff --git a/test/fixtures/test-runner/source-maps/invalid-json/index.js b/test/fixtures/test-runner/source-maps/invalid-json/index.js
new file mode 100644
index 00000000000000..f8a711af8c0098
--- /dev/null
+++ b/test/fixtures/test-runner/source-maps/invalid-json/index.js
@@ -0,0 +1,2 @@
+export {};
+//# sourceMappingURL=index.js.map
\ No newline at end of file
diff --git a/test/fixtures/test-runner/source-maps/invalid-json/index.js.map b/test/fixtures/test-runner/source-maps/invalid-json/index.js.map
new file mode 100644
index 00000000000000..e466dcbd8e8f2b
--- /dev/null
+++ b/test/fixtures/test-runner/source-maps/invalid-json/index.js.map
@@ -0,0 +1 @@
+invalid
\ No newline at end of file
diff --git a/test/fixtures/test-runner/source-maps/missing-map.js b/test/fixtures/test-runner/source-maps/missing-map.js
new file mode 100644
index 00000000000000..af68b844e0af61
--- /dev/null
+++ b/test/fixtures/test-runner/source-maps/missing-map.js
@@ -0,0 +1 @@
+//# sourceMappingURL=missing.js.map
\ No newline at end of file
diff --git a/test/parallel/test-runner-coverage-source-map.js b/test/parallel/test-runner-coverage-source-map.js
index 98752e757c542e..bba423dc7a8c47 100644
--- a/test/parallel/test-runner-coverage-source-map.js
+++ b/test/parallel/test-runner-coverage-source-map.js
@@ -80,4 +80,18 @@ describe('Coverage with source maps', async () => {
t.assert.ok(spawned.stdout.includes(error));
t.assert.strictEqual(spawned.code, 1);
});
+
+ for (const [file, message] of [
+ [fixtures.path('test-runner', 'source-maps', 'invalid-json', 'index.js'), 'is not valid JSON'],
+ [fixtures.path('test-runner', 'source-maps', 'missing-map.js'), 'does not exist'],
+ ]) {
+ await it(`should throw when a source map ${message}`, async (t) => {
+ const spawned = await common.spawnPromisified(process.execPath, [...flags, file]);
+
+ const error = `The source map for '${pathToFileURL(file)}' does not exist or is not valid JSON`;
+ t.assert.strictEqual(spawned.stderr, '');
+ t.assert.ok(spawned.stdout.includes(error));
+ t.assert.strictEqual(spawned.code, 1);
+ });
+ }
}).then(common.mustCall());