denoland/deno · error · ERR_CRYPTO_ECDH_INVALID_FORMAT
ERR_CRYPTO_ECDH_INVALID_FORMAT
ERR_CRYPTO_ECDH_INVALID_FORMAT
Error message
Invalid ECDH format: ${format} What it means
validateEcdhFormat (diffiehellman.ts:1356) validates the point-format parameter used by ECDH's getPublicKey and convertKey. Only 'compressed', 'uncompressed' and 'hybrid' are accepted; anything else throws ERR_CRYPTO_ECDH_INVALID_FORMAT naming the rejected value. Output encodings ('base64', 'hex') are a different parameter, which is the common confusion here.
Source
Thrown at ext/node/polyfills/internal/crypto/diffiehellman.ts:1356
getPublicKey(encoding?: any): Buffer | string {
return this.#diffiehellman.getPublicKey(encoding);
}
}
DiffieHellmanGroup.prototype = DiffieHellmanGroupImpl.prototype;
DiffieHellmanGroup.prototype.constructor = DiffieHellmanGroup;
function ECDH(curve: string) {
return new ECDHImpl(curve);
}
function validateEcdhFormat(format: any): void {
if (
format !== "compressed" &&
format !== "uncompressed" &&
format !== "hybrid"
) {
throw new ERR_CRYPTO_ECDH_INVALID_FORMAT(String(format));
}
}
function ecdhEncode(
buffer: Buffer,
encoding?: any,
): Buffer | string {
if (encoding === undefined || encoding === "buffer") {
return buffer;
}
// deno-lint-ignore deno-internal/prefer-primordials -- Buffer.prototype.toString(encoding) has no primordial
return buffer.toString(encoding);
}
class ECDHImpl {
#curve: any; // the selected curve
#privbuf: Buffer | null = null; // the private key
#pubbuf: Buffer | null = null; // the public keyView on GitHub (pinned to 9ad36f7a2c)
Solutions
- Remember the order: getPublicKey(encoding, format) — encoding first, format second
- Use only 'compressed' | 'uncompressed' | 'hybrid' for the format parameter
- If you just want text output, pass the encoding and omit the format: getPublicKey('base64')
Example fix
// before
ecdh.getPublicKey('base64', 'hex'); // 'hex' lands in format -> ERR_CRYPTO_ECDH_INVALID_FORMAT
// after
ecdh.getPublicKey('base64'); // encoding only, uncompressed point
// or explicit point format:
ecdh.getPublicKey(null, 'compressed').toString('base64'); Defensive patterns
Strategy: validation
Validate before calling
const ECDH_FORMATS = new Set(['compressed', 'uncompressed', 'hybrid']);
function assertPointFormat(fmt) {
if (fmt !== undefined && !ECDH_FORMATS.has(fmt)) throw new TypeError(`invalid ECDH format: ${fmt}`);
} Type guard
const isEcdhPointFormat = (f) => f === undefined || f === 'compressed' || f === 'uncompressed' || f === 'hybrid';
Try / catch
try { key = ecdh.getPublicKey(null, fmt); } catch (e) { if (e?.code === 'ERR_CRYPTO_ECDH_INVALID_FORMAT') { key = ecdh.getPublicKey(null, 'uncompressed'); } else throw e; } Prevention
- Remember getPublicKey(encoding, format) — the encoding comes first
- Define a union type 'compressed' | 'uncompressed' | 'hybrid' for the format parameter
When it happens
Trigger: ecdh.getPublicKey(null, 'base64') — an output encoding passed in the format slot; convertKey(key, curve, inEnc, outEnc, 'hex'); capitalized variants like 'Compressed'; format names invented from WebCrypto ('raw', 'spki').
Common situations: Argument-order mix-ups because getPublicKey(encoding, format) takes the encoding first; passing every string option into the format position; copy-paste from APIs with different parameter orders.
Related errors
- ERR_INVALID_ARG_TYPE
- Invalid EC curve name
- ERR_CRYPTO_ECDH_INVALID_PUBLIC_KEY
- Invalid key pair
- Failed to get ECDH private key
AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20).
Data as JSON: /api/errors/f4972dfe5e475ce6.
Report an issue: GitHub.