denoland/deno · error · ERR_INVALID_ARG_TYPE

ERR_INVALID_ARG_TYPE

ERR_INVALID_ARG_TYPE

Error message

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

What it means

Hash.update() accepts only strings and ArrayBuffer views (Buffer, TypedArray, DataView); any other value — number, null, plain object, BigInt — throws ERR_INVALID_ARG_TYPE for 'data'. Strings are additionally checked against the requested encoding before being fed to the native op.

Source

Thrown at ext/node/polyfills/internal/crypto/hash.ts:189

};

Hash.prototype._flush = function _flush(callback: () => void) {
  const digest = op_node_hash_digest(this[kHandle]);
  // deno-lint-ignore deno-internal/prefer-primordials -- `this` is a Node stream (Transform)
  this.push(digest === null ? Buffer.alloc(0) : Buffer.from(digest));
  callback();
};

Hash.prototype.update = function update(
  data: string | Buffer,
  encoding: any,
) {
  encoding = encoding || getDefaultEncoding();

  if (typeof data === "string") {
    validateEncoding(data, encoding);
  } else if (!isArrayBufferView(data)) {
    throw new ERR_INVALID_ARG_TYPE(
      "data",
      ["string", "Buffer", "TypedArray", "DataView"],
      data,
    );
  }

  if (
    typeof data === "string" && (encoding === "utf8" || encoding === "buffer")
  ) {
    unwrapErr(op_node_hash_update_str(this[kHandle], data));
  } else {
    const buf = toBuf(data as string | Buffer, encoding);
    const u8 = ObjectPrototypeIsPrototypeOf(Uint8ArrayPrototype, buf)
      ? buf as Uint8Array
      : new Uint8Array(
        // deno-lint-ignore deno-internal/prefer-primordials -- ArrayBufferView accessor, receiver may be a DataView
        (buf as ArrayBufferView).buffer,
        // deno-lint-ignore deno-internal/prefer-primordials -- ArrayBufferView accessor, receiver may be a DataView

View on GitHub (pinned to 9ad36f7a2c)

Solutions

  1. Convert non-string inputs to Buffer first: h.update(Buffer.from(String(id))) or h.update(Uint8Array)
  2. Null-check optional fields before updating and skip or substitute an empty string
  3. Verify function calls actually happened: JSON.stringify(payload), not JSON.stringify

Example fix

// before
h.update(user.id); // number

// after
h.update(String(user.id));
Defensive patterns

Strategy: type-guard

Type guard

const isHashData = (v: unknown): v is string | Buffer | Uint8Array | DataView =>
  typeof v === 'string' || ArrayBuffer.isView(v);

Prevention

When it happens

Trigger: h.update(123), h.update(null), h.update(BigInt(42)), or h.update(someObject) where a serialization step was forgotten (e.g. passing JSON.stringify instead of JSON.stringify(x) — a function reference).

Common situations: Feeding numeric IDs or counters directly into an HMAC; null creeping in from optional fields; forgetting to call a value-producing function; passing a Node Buffer from a different realm/monkey-patched environment that fails the view check.

Understand the failure class

Background: Invalid argument type errors: "must be of type string", "expected X, got Y", and ERR_INVALID_ARG_TYPE explained — this error's family across 15 libraries.

Related errors


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