denoland/deno · error · Error
Failed to convert Buffer to EC_POINT
Error message
Failed to convert Buffer to EC_POINT
What it means
A generic Error thrown by ECDH.convertKey() when op_node_ecdh_encode_pubkey fails for any reason other than an unsupported curve. It means the key bytes could not be parsed as a public key EC point on the specified curve — the buffer never became an EC_POINT, so it cannot be re-encoded to compressed/uncompressed/hybrid form.
Source
Thrown at ext/node/polyfills/internal/crypto/diffiehellman.ts:1422
throw new ERR_CRYPTO_ECDH_INVALID_FORMAT(format);
}
} else {
compress = false;
}
let result;
try {
result = Buffer.from(
op_node_ecdh_encode_pubkey(curve, buf, compress),
);
} catch (e) {
if (
ObjectPrototypeIsPrototypeOf(TypeErrorPrototype, e) &&
(e as Error).message === "Unsupported curve"
) {
throw new TypeError("Invalid EC curve name");
}
throw new Error("Failed to convert Buffer to EC_POINT");
}
if (format === "hybrid") {
// Hybrid format: same as uncompressed but first byte is 06 or 07
// Get compressed form to determine parity
const compressedBuf = Buffer.from(
op_node_ecdh_encode_pubkey(curve, buf, true),
);
// compressed first byte is 02 (even) or 03 (odd)
// hybrid first byte is 06 (even) or 07 (odd)
result[0] = compressedBuf[0] + 4;
}
if (outputEncoding && outputEncoding !== "buffer") {
// deno-lint-ignore deno-internal/prefer-primordials -- Buffer.prototype.toString(encoding) has no primordial
return result.toString(outputEncoding);
}
return result;View on GitHub (pinned to 9ad36f7a2c)
Solutions
- Verify the input length: uncompressed points are 1 + 2*fieldSize bytes (P-256: 65, P-384: 97, P-521: 133), compressed are 1 + fieldSize
- Check the first byte is 0x04 (uncompressed) or 0x02/0x03 (compressed) and prepend 0x04 if the peer sent bare X||Y coordinates
- Confirm inputEncoding matches how the key was produced (a hex string must be read with 'hex')
- Make sure you are converting a public key, not a private scalar or a DER/PEM blob — decode those first
Example fix
// before const point = Buffer.concat([x, y]); // 64 bytes, no prefix const out = crypto.ECDH.convertKey(point, 'prime256v1'); // after const point = Buffer.concat([Buffer.from([0x04]), x, y]); // 65 bytes with 0x04 prefix const out = crypto.ECDH.convertKey(point, 'prime256v1');
Defensive patterns
Strategy: validation
Validate before calling
const FIELD = { prime256v1: 32, secp384r1: 48, secp521r1: 66 }[curve]!;
const ok = buf.length === 1 + 2 * FIELD && buf[0] === 0x04;
if (!ok) throw new RangeError('key is not an uncompressed point for ' + curve);
const out = crypto.ECDH.convertKey(key, curve, inputEncoding, outputEncoding, format); Type guard
const isUncompressedPoint = (b: Uint8Array, fieldSize: number): boolean => b.length === 1 + 2 * fieldSize && (b[0] === 0x04 || b[0] === 0x06 || b[0] === 0x07);
Try / catch
catch (e) { if (e.message === 'Failed to convert Buffer to EC_POINT') { /* reject peer key, re-request */ } throw e; } Prevention
- Agree on a single point-encoding (prefixed uncompressed) in your protocol spec
- Validate key length and prefix byte at the trust boundary before any crypto op
- Always pair key strings with the encoding they were produced with
When it happens
Trigger: Passing key bytes with the wrong length for the curve (e.g. 64 raw bytes instead of a 65-byte 0x04-prefixed point for P-256), a missing or invalid prefix byte (0x02/0x03/0x04), a point that is not on the curve, or a private key / random data supplied where a public key point is expected.
Common situations: Peer systems send the raw X||Y coordinates without the uncompressed 0x04 header; hex strings decoded with the wrong encoding ('base64' vs 'hex'); passing a Buffer that was sliced with wrong offsets; feeding a secp256k1 key into a prime256v1 conversion.
Related errors
- ERR_INVALID_ARG_VALUE
- ERR_UNKNOWN_ENCODING
- ERR_CRYPTO_ECDH_INVALID_FORMAT
- invalid curve
- Invalid EC curve name
AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20).
Data as JSON: /api/errors/91a815ec3c9b979d.
Report an issue: GitHub.