denoland/deno · error · ERR_INVALID_ARG_VALUE

ERR_INVALID_ARG_VALUE

ERR_INVALID_ARG_VALUE

Error message

The property 'exportNames.${name}' is duplicated. Received ${name}

What it means

Thrown by the vm.SyntheticModule constructor when exportNames contains the same string more than once (vm.js:850-857). Each export name must be unique because each maps to one slot on the synthetic namespace; duplicates would collide at setExport time, so they are rejected eagerly.

Source

Thrown at ext/node/polyfills/vm.js:853

  }
}

class SyntheticModule extends Module {
  constructor(exportNames, evaluateCallback, options = { __proto__: null }) {
    super();
    if (
      !ArrayIsArray(exportNames) ||
      ArrayPrototypeSome(exportNames, (e) => typeof e !== "string")
    ) {
      throw new ERR_INVALID_ARG_TYPE(
        "exportNames",
        "Array of unique strings",
        exportNames,
      );
    }
    ArrayPrototypeForEach(exportNames, (name, i) => {
      if (ArrayPrototypeIndexOf(exportNames, name, i + 1) !== -1) {
        throw new ERR_INVALID_ARG_VALUE(
          `exportNames.${name}`,
          name,
          "is duplicated",
        );
      }
    });
    if (typeof evaluateCallback !== "function") {
      throw new ERR_INVALID_ARG_TYPE(
        "evaluateCallback",
        "function",
        evaluateCallback,
      );
    }
    validateObject(options, "options");
    const {
      identifier = `vm:module(${defaultModuleIdIndex++})`,
      context,
    } = options;

View on GitHub (pinned to 9ad36f7a2c)

Solutions

  1. Dedupe before constructing: `[...new Set(names)]`
  2. When wrapping CJS, exclude an existing default: `['default', ...Object.keys(exports).filter(k => k !== 'default')]`
  3. Add a dev-time assert on uniqueness: `new Set(names).size === names.length`
  4. Fix the generator that produces the list rather than catching the error

Example fix

// before
new vm.SyntheticModule(['default', 'foo', 'default'], cb);
// after
new vm.SyntheticModule([...new Set(['default', 'foo', 'default'])], cb);
Defensive patterns

Strategy: validation

Validate before calling

if (new Set(exportNames).size !== exportNames.length) {
  throw new Error(`duplicate export names: ${exportNames}`);
}
new vm.SyntheticModule(exportNames, cb);

Try / catch

try { new vm.SyntheticModule(names, cb); }
catch (e) { if (e.code === 'ERR_INVALID_ARG_VALUE' && /duplicated/.test(e.message)) names = [...new Set(names)]; else throw e; }

Prevention

When it happens

Trigger: `['default', 'foo', 'default']` from concatenating a default-export list with a named-export list that already includes 'default'; merging export lists from multiple sources without deduping; descriptor arrays generated by spreading two configs; typos duplicated by code generation.

Common situations: Building a synthetic facade over a CJS module: `['default', ...Object.keys(module.exports)]` where module.exports already has a `default` key; aggregating re-exports from several sub-modules into one synthetic barrel; codemods or generators that append rather than replace.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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