denoland/deno · error · TypeError

BenchContext::start() has already been invoked

Error message

BenchContext::start() has already been invoked

What it means

Every executable name — whether given via `--name` or inferred from the module URL / package bin map — must match `^[a-z0-9][\w-]*$` (case-insensitive). That means: starts with an ASCII letter or digit, followed only by letters, digits, underscore, or hyphen. `validate_name` runs after inference, so even a successfully inferred name can be rejected if it contains characters like spaces or slashes.

Solutions

  1. Choose a name matching `[a-zA-Z0-9][a-zA-Z0-9_-]*`, e.g. `--name my-tool`
  2. Strip scopes/slashes/spaces before passing `--name`
  3. For scoped packages, let inference use the package's bin entry, or pass an explicit flat name

Example fix

# before
$ deno install -g --name "@scope/tool" https://example.com/x.ts
# Invalid executable name: @scope/tool

# after
$ deno install -g --name scope-tool https://example.com/x.ts
Defensive patterns

Strategy: type-guard

Validate before calling

// Validate a chosen bin name the same way deno does
const VALID = /^[a-z0-9][\w-]*$/i;
export const isValidExecName = (n: string) => VALID.test(n);

Type guard

function isValidExecName(name: string): boolean {
  return /^[a-z0-9][\w-]*$/i.test(name);
}

Prevention

When it happens

Trigger: `deno install -g --name 'my tool' <url>` (space), `--name '-foo'` (leading dash), `--name '@scope/tool'` or `--name 'a/b'` (slash), or a URL-derived name containing invalid characters (e.g. a directory segment with a space, like the inference of `https://example.com/ab%20c/mod.ts` to `ab c`).

Common situations: Trying to keep npm-style scoped names (`@scope/pkg`) as bin names; copy-pasting display names with spaces; URL directory segments that contain encoded spaces or other non-word characters.

Related errors


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

Appendix: source

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

    allSlice,
    allLength,
  );
}

/** @param desc {BenchDescription} */
function createBenchContext(desc) {
  return {
    [SymbolToStringTag]: "BenchContext",
    name: desc.name,
    origin: desc.origin,
    start() {
      if (currentBenchId !== desc.id) {
        throw new TypeError(
          "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;
    },
  };

View on GitHub (pinned to 9ad36f7a2c)