{"id":"55b35cc5593edc3e","repo":"jestjs/jest","slug":"could-not-resolve-a-module-for-a-custom-reporter","errorCode":null,"errorMessage":"Could not resolve a module for a custom reporter.\n  Module name: ${reporterPath}","messagePattern":"Could not resolve a module for a custom reporter\\.\n  Module name: (.+?)","errorType":"exception","errorClass":"ModuleNotFoundError","httpStatus":null,"severity":"error","filePath":"packages/jest-config/src/normalize.ts","lineNumber":437,"sourceCode":"        ? // if reporter config is a string, we wrap it in an array\n          // and pass an empty object for options argument, to normalize\n          // the shape.\n          [reporterConfig, {}]\n        : reporterConfig;\n\n    const reporterPath = replaceRootDirInPath(\n      rootDir,\n      normalizedReporterConfig[0],\n    );\n\n    if (\n      !['agent', 'default', 'github-actions', 'summary'].includes(reporterPath)\n    ) {\n      const reporter = Resolver.findNodeModule(reporterPath, {\n        basedir: rootDir,\n      });\n      if (!reporter) {\n        throw new Resolver.ModuleNotFoundError(\n          'Could not resolve a module for a custom reporter.\\n' +\n            `  Module name: ${reporterPath}`,\n        );\n      }\n      normalizedReporterConfig[0] = reporter;\n    }\n    return normalizedReporterConfig;\n  });\n};\n\nconst buildTestPathPatterns = (argv: Config.Argv): TestPathPatterns => {\n  const patterns = [];\n\n  if (argv._) {\n    patterns.push(...argv._.map(x => x.toString()));\n  }\n  if (argv.testPathPatterns) {\n    patterns.push(...argv.testPathPatterns);","sourceCodeStart":419,"sourceCodeEnd":455,"githubUrl":"https://github.com/jestjs/jest/blob/f49721c78e195558b40913977c9230f5b7f559d8/packages/jest-config/src/normalize.ts#L419-L455","documentation":"`normalizeReporters` (packages/jest-config/src/normalize.ts:404) resolves each custom reporter path via the module resolver; if `Resolver.findNodeModule` returns null (and the name is not one of the built-ins 'default','agent','github-actions','summary'), it throws a `Resolver.ModuleNotFoundError`. The built-in names skip resolution.","triggerScenarios":"`reporters: ['jest-dot-reporter']` where the package is not installed; a path like `<rootDir>/reporters/myReporter.js` that does not exist; typo in the reporter module name.","commonSituations":"Adding a custom reporter to config without installing it; reporter moved/renamed; CI environment missing a devDependency due to `--production` install or pruned lockfile.","solutions":["Install the reporter package: `npm install --save-dev <reporter>`.","Verify the path/name resolves from `rootDir` (use `require.resolve('<reporter>')` in a scratch script to test).","If you only want a built-in reporter, use one of the recognized names: 'default', 'summary', 'github-actions'."],"exampleFix":"// before\nmodule.exports = { reporters: ['jest-junit'] }; // not installed\n\n// after\n// npm install --save-dev jest-junit\nmodule.exports = { reporters: ['default', 'jest-junit'] };","handlingStrategy":"try-catch","validationCode":"import {Resolver} from 'jest-resolve';\nconst BUILTIN = new Set(['default','agent','github-actions','summary']);\nfunction assertReporterResolvable(name: string, rootDir: string): void {\n  if (BUILTIN.has(name)) return;\n  if (!Resolver.findNodeModule(name, { basedir: rootDir })) {\n    throw new Error(`Reporter '${name}' not resolvable from ${rootDir}`);\n  }\n}","typeGuard":"const isBuiltinReporter = (n: string) =>\n  ['default','agent','github-actions','summary'].includes(n);","tryCatchPattern":"try {\n  require.resolve(reporterPath, { paths: [rootDir] });\n} catch {\n  throw new Error(`Custom reporter '${reporterPath}' missing; npm i -D ${reporterPath}`);\n}","preventionTips":["Install custom reporters as devDependencies in every environment that runs tests.","Use require.resolve in a smoke check to verify resolvability.","Prefer built-in reporter names when possible."],"tags":["jest-config","reporters","module-resolution","config"],"analyzedSha":"f49721c78e195558b40913977c9230f5b7f559d8","analyzedAt":"2026-08-03T20:16:28.571Z","schemaVersion":2}