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 DataViewView on GitHub (pinned to 9ad36f7a2c)
Solutions
- Convert non-string inputs to Buffer first: h.update(Buffer.from(String(id))) or h.update(Uint8Array)
- Null-check optional fields before updating and skip or substitute an empty string
- 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
- Coerce IDs/numbers with String() before updating
- Null-check optional fields and skip or use '' when absent
- In TypeScript, type the update() parameter as string | Buffer | Uint8Array
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
- ERR_INVALID_ARG_TYPE
- ERR_INVALID_ARG_VALUE
- ERR_INVALID_ARG_VALUE
- ERR_INVALID_ARG_VALUE
- ERR_CRYPTO_HASH_FINALIZED
AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20).
Data as JSON: /api/errors/c19a30b7f9ac51ef.
Report an issue: GitHub.