denoland/deno · error · TypeError

BenchContext::end() has already been invoked

Error message

BenchContext::end() has already been invoked

What it means

`deno ci` requires a lockfile and then deletes the existing `node_modules` directory for a clean, reproducible install. This wrapper reports the underlying `fs::remove_dir_all` failure with the directory path, keeping the original OS error (`{err}`) in the message. It fails before any dependency is installed, so the environment is left as-is.

Solutions

  1. Stop processes that hold files in node_modules (dev servers, editors, running tools) and re-run `deno ci`
  2. Fix ownership if a sudo run created root-owned files: `sudo chown -R "$(id -un):$(id -gn)" node_modules` then retry
  3. Delete manually if removal is stuck: `rm -rf node_modules` (Windows: close apps first or use `rmdir /s /q node_modules`) then re-run
  4. Avoid running deno with sudo; ensure CI mounts are writable

Example fix

# before
$ deno ci
# failed to remove .../node_modules: Directory not empty (os error 39)

# after
$ sudo chown -R "$(id -un)" node_modules && rm -rf node_modules
$ deno ci  # clean install succeeds
Defensive patterns

Strategy: retry

Validate before calling

# Pre-flight: confirm node_modules is removable before deno ci
[ ! -d node_modules ] || { touch node_modules/.probe && rm node_modules/.probe; } || echo "node_modules not writable — fix perms first"

Try / catch

Wrap `deno ci` with bounded retry on this message: the classic cause (a process holding files) resolves once that process exits — kill dev servers/editors, wait a few seconds, retry once or twice; if the message persists, fall back to `rm -rf node_modules` and a final `deno ci`.

Prevention

When it happens

Trigger: `deno ci` when `node_modules` exists and cannot be removed: a file inside is held open by a running process (dev server, editor, esbuild service — classic on Windows), the directory or its contents are owned by another user (previous sudo run), or the filesystem is read-only (container, CI cache mount).

Common situations: Windows developers with a running `deno task dev`/editor holding DLLs/JS files; unix users who previously ran `sudo deno install` leaving root-owned files; CI with a read-only or incorrectly permissioned cache volume.

Related errors


AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20). Data as JSON: /api/errors/0958e05beb001d1a. Report an issue: GitHub.

Appendix: source

Thrown at cli/js/40_bench.js:446

          "The benchmark which this context belongs to is not being executed",
        );
      }
      if (currentBenchUserExplicitStart != null) {
        throw new TypeError(
          "BenchContext::start() has already been invoked",
        );
      }
      currentBenchUserExplicitStart = benchNow();
    },
    end() {
      const end = benchNow();
      if (currentBenchId !== desc.id) {
        throw new TypeError(
          "The benchmark which this context belongs to is not being executed",
        );
      }
      if (currentBenchUserExplicitEnd != null) {
        throw new TypeError("BenchContext::end() has already been invoked");
      }
      currentBenchUserExplicitEnd = end;
    },
  };
}

/** Wrap a user benchmark function in one which returns a structured result. */
function wrapBenchmark(desc) {
  const fn = desc.fn;
  return async function outerWrapped() {
    let token = null;
    const originalConsole = globalThis.console;
    currentBenchId = desc.id;

    try {
      globalThis.console = new Console((s) => {
        op_dispatch_bench_event({ output: s });
      });

View on GitHub (pinned to 9ad36f7a2c)