denoland/deno · error · TypeError

ERR_INVALID_ARG_TYPE

ERR_INVALID_ARG_TYPE

Error message

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

What it means

Verify.verify(publicKey, signature, encoding) requires signature to be a string or an ArrayBufferView (Buffer, TypedArray, DataView); any other value throws ERR_INVALID_ARG_TYPE. A raw ArrayBuffer is rejected because it is not a view — only the bytes are needed, so wrap it. Strings are later decoded using the third encoding argument.

Source

Thrown at ext/node/polyfills/internal/crypto/sig.ts:292

      throw new Error(`Invalid digest: ${algorithm}`);
    }
  }

  update(data: any, encoding?: string): this {
    this.hash.update(data, encoding);
    return this;
  }

  verify(
    publicKey: any,
    signature: any,
    encoding?: any,
  ): boolean {
    if (
      typeof signature !== "string" &&
      !ArrayBufferIsView(signature)
    ) {
      throw new ERR_INVALID_ARG_TYPE(
        "signature",
        ["Buffer", "TypedArray", "DataView"],
        signature,
      );
    }
    const res = prepareAsymmetricKey(publicKey, kConsumePublic);

    // Options specific to RSA
    const rsaPadding = getPadding(publicKey);

    // Options specific to RSA-PSS
    const pssSaltLength = getSaltLength(publicKey);

    // Options specific to (EC)DSA
    const dsaSigEnc = getDSASignatureEncoding(publicKey);

    let handle;
    if (ReflectHas(res, "handle")) {

View on GitHub (pinned to 9ad36f7a2c)

Solutions

  1. Wrap ArrayBuffers: verify.verify(pubKey, new Uint8Array(ab)) or Buffer.from(ab).
  2. Convert encoded signatures explicitly: Buffer.from(base64Sig, "base64").
  3. Check the signature variable is defined and not shadowed before calling verify().

Example fix

// before
const sig = await res.arrayBuffer(); // ArrayBuffer, not a view
verifier.verify(pubKey, sig); // throws

// after
const sig = new Uint8Array(await res.arrayBuffer());
verifier.verify(pubKey, sig);
Defensive patterns

Strategy: type-guard

Validate before calling

function toSignatureBytes(sig) {
  if (typeof sig === "string") return Buffer.from(sig, "base64");
  if (ArrayBuffer.isView(sig)) return Buffer.from(sig);
  throw new TypeError(`signature must be string or TypedArray, got ${typeof sig}`);
}
verifier.verify(pubKey, toSignatureBytes(sigFromHttp));

Type guard

const isSignaturable = (v) => typeof v === "string" || ArrayBuffer.isView(v);

Try / catch

try {
  ok = verifier.verify(pubKey, sig);
} catch (e) {
  if (e?.code === "ERR_INVALID_ARG_TYPE" && /^The "signature"/.test(e.message)) {
    return res.status(400).end("malformed signature payload");
  }
  throw e;
}

Prevention

When it happens

Trigger: verify.verify(pubKey, sig) where sig is an ArrayBuffer from response.arrayBuffer(); a number, null, plain object, or undefined in the signature slot; passing a parsed JSON object that contains the signature bytes.

Common situations: Verifying signatures received over HTTP (fetch's res.arrayBuffer() returns an ArrayBuffer, not a view); WebCrypto interop where subtle operations return ArrayBuffers; passing base64 text without Buffer.from(sig, "base64").

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