denoland/deno · error · ERR_INVALID_ARG_TYPE

ERR_INVALID_ARG_TYPE

ERR_INVALID_ARG_TYPE

Error message

The "${name}" argument must be of type object. Received ${value}

What it means

Local validateObject in the WASI polyfill (wasi.ts:88-95) throws ERR_INVALID_ARG_TYPE for the WASI constructor's `options`, `options.env`, and `options.preopens` when the value is null, not an object, or an Array. It is stricter than a plain typeof check — arrays are explicitly rejected even though typeof [] === 'object'.

Source

Thrown at ext/node/polyfills/wasi.ts:93

    `The "instance.exports.memory" property must be a WebAssembly.Memory object. Received ${received}`,
  );
  (err as unknown as { code: string }).code = "ERR_INVALID_ARG_TYPE";
  return err;
}

class WASIProcExit {
  code: number;
  constructor(code: number) {
    this.code = code;
  }
}

function validateObject(
  value: unknown,
  name: string,
): asserts value is object {
  if (value === null || typeof value !== "object" || ArrayIsArray(value)) {
    throw new ERR_INVALID_ARG_TYPE(name, "object", value);
  }
}

function validateArray(
  value: unknown,
  name: string,
): asserts value is unknown[] {
  if (!ArrayIsArray(value)) {
    throw new ERR_INVALID_ARG_TYPE(name, "Array", value);
  }
}

function validateBoolean(
  value: unknown,
  name: string,
): asserts value is boolean {
  if (typeof value !== "boolean") {
    throw new ERR_INVALID_ARG_TYPE(name, "boolean", value);

View on GitHub (pinned to 9ad36f7a2c)

Solutions

  1. Use object maps: `new WASI({ version: 'preview1', env: { A: '1' }, preopens: { '/sandbox': './data' } })`
  2. Convert pair arrays first: `Object.fromEntries(pairs)`
  3. Default missing maps explicitly: `env: envMap ?? {}`
  4. Reject arrays at the boundary if your config layer might deliver them

Example fix

// before
new WASI({ version: 'preview1', env: [['A','1']], preopens: ['/data'] });
// after
new WASI({
  version: 'preview1',
  env: Object.fromEntries([['A', '1']]),
  preopens: { '/data': './data' },
});
Defensive patterns

Strategy: type-guard

Validate before calling

const isPlainObject = (v) =>
  typeof v === 'object' && v !== null && !Array.isArray(v);
if (!isPlainObject(opts.env)) opts.env = {};
if (!isPlainObject(opts.preopens)) opts.preopens = {};
new WASI({ version: 'preview1', ...opts });

Type guard

const isPlainObject = (v) => typeof v === 'object' && v !== null && !Array.isArray(v);

Try / catch

try { new WASI(opts); }
catch (e) { if (e.code === 'ERR_INVALID_ARG_TYPE' && /env|preopens|options/.test(e.message)) { /* convert pair arrays with Object.fromEntries and retry */ } else throw e; }

Prevention

When it happens

Trigger: `new WASI(null)`; `new WASI(new SomeClass())` is fine but `new WASI('preview1')` (string) is not; `env: [['A','1']]` as an array of pairs instead of a map object; `preopens: ['/tmp']` as an array instead of `{ virtual: real }`; `env: 'A=1'` shell-style strings.

Common situations: Transluting shell/env semantics into options: developers pass env as `KEY=VALUE` strings or entry arrays (child_process.spawn style) instead of an object map; passing preopens as an array of paths; deserialized JSON options where env became null; mixing up spawn({env}) object style with exec string style.

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/bb53e62e96a32896. Report an issue: GitHub.