Skip to content
This repository was archived by the owner on Aug 30, 2026. It is now read-only.
This repository was archived by the owner on Aug 30, 2026. It is now read-only.

@mergifyio/vitest@0.3.0: _configureRunner resolves dist/runner.js (ships .mjs/.cjs) → ERR_MODULE_NOT_FOUND under Vitest 4.x in CI #169

Description

@seamnniel

Summary

@mergifyio/vitest@0.3.0 (latest) breaks every test run in CI once the quarantine/flaky runner activates. MergifyReporter._configureRunner resolves the runner as dist/runner.js, but the package only ships dist/runner.mjs and dist/runner.cjs — there is no runner.js. Under Vitest 4.x this throws ERR_MODULE_NOT_FOUND and aborts the entire suite.

Root cause

_configureRunner builds the runner path with a hardcoded "runner.js":

// dist/index.mjs:116
const mergifyRunner = resolve(
  typeof __dirname !== "undefined" ? __dirname : dirname(fileURLToPath(import.meta.url)),
  "runner.js"
);
if (!vitest.config.runner) vitest.config.runner = mergifyRunner;
// dist/index.cjs:120
const mergifyRunner = (0, node_path.resolve)(/* … */, "runner.js");

But the build emits runner.mjs / runner.cjs (and the package exports map exposes them via ./runnerimport: dist/runner.mjs, require: dist/runner.cjs). So the resolved absolute path …/dist/runner.js does not exist.

$ ls node_modules/@mergifyio/vitest/dist
index.cjs  index.mjs  runner.cjs  runner.mjs  …   # no runner.js

Reproduction

  • Vitest 4.1.8, @mergifyio/vitest@0.3.0, ESM vite.config.ts registering new MergifyReporter().
  • In CI (isInCI() true) with MERGIFY_TOKEN set and a non-empty quarantine list (so _configureRunner runs), every test errors:
Error: Cannot find module '…/node_modules/.pnpm/@mergifyio+vitest@0.3.0…/dist/runner.js'
  imported from …/vitest/dist/module-evaluator.js
{ code: 'ERR_MODULE_NOT_FOUND', url: 'file://…/dist/runner.js' }

It passes locally only because the reporter is gated on isInCI().

Suggested fix

Resolve the runner via the package's own ./runner export (so the correct .mjs/.cjs is chosen per build), e.g.:

const mergifyRunner = fileURLToPath(import.meta.resolve("@mergifyio/vitest/runner"));

or emit the runner with the same extension the entry resolves (runner.mjs from index.mjs, runner.cjs from index.cjs).

Workaround (for others hitting this)

Pre-pin the runner in your Vitest config so the reporter's broken assignment is skipped:

import { fileURLToPath } from "node:url";
const mergifyRunner = fileURLToPath(import.meta.resolve("@mergifyio/vitest/runner"));

export default defineConfig({
  test: {
    runner: mergifyRunner,
    reporters: ["default", new MergifyReporter()],
  },
});

Thanks for the plugin! Happy to test a patch.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions