denoland/deno · error · TypeError

ERR_INVALID_ARG_TYPE

ERR_INVALID_ARG_TYPE

Error message

The "${name}" argument must be of type string or an instance of Buffer, TypedArray, or DataView. Received ${item}

What it means

The shared key/cert validator walks arrays element by element: falsy entries are skipped, valid PEM carriers (string, Buffer, TypedArray, DataView) pass, and for key arrays plain objects such as { pem, passphrase } are tolerated. Any other truthy item - a number, a Promise, or a random object inside a cert array - throws ERR_INVALID_ARG_TYPE for that item.

Source

Thrown at ext/node/polyfills/_tls_common.ts:386

}

function validateKeyCertOption(
  val: any,
  name: string,
  allowKeyObjects: boolean,
) {
  if (!val) return; // falsy values (false, null, undefined, 0, '') are skipped
  if (isValidKeyCertValue(val)) return;
  if (ArrayIsArray(val)) {
    for (let i = 0; i < val.length; i++) {
      const item = val[i];
      if (!item) continue;
      if (isValidKeyCertValue(item)) continue;
      // For key, objects like { pem, passphrase } are allowed inside arrays
      if (
        allowKeyObjects && typeof item === "object" && item !== null
      ) continue;
      throw new ERR_INVALID_ARG_TYPE(
        name,
        ["string", "Buffer", "TypedArray", "DataView"],
        item,
      );
    }
    return;
  }
  throw new ERR_INVALID_ARG_TYPE(
    name,
    ["string", "Buffer", "TypedArray", "DataView"],
    val,
  );
}

function toUint8Array(val: any): Uint8Array {
  if (typeof val === "string") {
    return new TextEncoder().encode(val);
  }

View on GitHub (pinned to 89f33cbef2)

Solutions

  1. Await all file reads before building the array
  2. Map entries to strings/Buffers and filter out non-PEM values
  3. Keep the { pem, passphrase } object form only where the API allows it (key arrays)
  4. Validate items with an isPemValue guard before createSecureContext

Example fix

// before
const certs = [fs.promises.readFile('a.pem'), 'b.pem']; // Promise item throws
tls.createSecureContext({ cert: certs });

// after
const certs = await Promise.all([
  fs.promises.readFile('a.pem'),
  fs.promises.readFile('b.pem'),
]);
tls.createSecureContext({ cert: certs });
Defensive patterns

Strategy: type-guard

Validate before calling

function isPemValue(v) {
  if (!v) return true; // falsy entries are skipped by the API
  if (typeof v === 'string') return true;
  if (typeof v === 'object' && v !== null && typeof v.byteLength === 'number') return true; // Buffer/TypedArray/DataView
  return false;
}
function validKeyCertArray(name, arr, allowKeyObjects) {
  return arr.every((item) =>
    isPemValue(item) || (allowKeyObjects && typeof item === 'object' && item !== null));
}
if (validKeyCertArray('cert', certs, false)) tls.createSecureContext({ cert: certs });

Type guard

const isPemCarrier = (v) =>
  typeof v === 'string' || (v !== null && typeof v === 'object' && typeof v.byteLength === 'number');

Try / catch

try {
  ctx = tls.createSecureContext({ key, cert });
} catch (e) {
  if (e.code === 'ERR_INVALID_ARG_TYPE' && /key|cert/.test(e.message)) {
    // an array item was not a string/Buffer/TypedArray/DataView: log and reject config
  } else throw e;
}

Prevention

When it happens

Trigger: tls.createSecureContext({ cert: [certPem, 42] }); passing fs.promises.readFile() results without await (Promise objects) inside a cert array; parsed JSON entries mixed into cert/key arrays; objects allowed only for key arrays used in cert arrays.

Common situations: Loading multiple certs or passphrase-protected keys with Promise.all where one await was forgotten; config arrays typed as any that pick up non-PEM values; utility functions that sometimes return parsed objects instead of raw buffers.

Related errors


AI-assisted analysis of denoland/deno@89f33cbef2 (2026-08-16). Data as JSON: /api/errors/3e14d757e2d7af53. Report an issue: GitHub.