denoland/deno · error · Error
Session ticket keys must be a 48-byte buffer
Error message
Session ticket keys must be a 48-byte buffer
What it means
The second guard in setTicketKeys enforces the TLS session-ticket key size: exactly 48 bytes (16 name + 16 HMAC key + 16 AES key, ext/node/polyfills/_tls_wrap.js:1519). Unlike the constructor path, which throws the coded ERR_INVALID_ARG_VALUE, this runtime-rotation path throws a plain Error('Session ticket keys must be a 48-byte buffer').
Source
Thrown at ext/node/polyfills/_tls_wrap.js:1519
throw new ERR_TLS_REQUIRED_SERVER_NAME();
}
ArrayPrototypePush(this._contexts, [servername, context]);
};
Server.prototype.getTicketKeys = function getTicketKeys() {
return Buffer.from(this._ticketKeys);
};
Server.prototype.setTicketKeys = function setTicketKeys(keys) {
if (!isArrayBufferView(keys)) {
throw new ERR_INVALID_ARG_TYPE(
"keys",
["Buffer", "TypedArray", "DataView"],
keys,
);
}
if (getViewByteLength(keys) !== 48) {
throw new Error("Session ticket keys must be a 48-byte buffer");
}
this._ticketKeys = Buffer.from(
getViewBuffer(keys),
getViewByteOffset(keys),
getViewByteLength(keys),
);
};
// ---------------------------------------------------------------------------
// connect
// ---------------------------------------------------------------------------
function onConnectEnd() {
if (!this._hadError) {
const options = this[kConnectOptions];
this._hadError = true;
const error = connResetException(
"Client network socket disconnected " +View on GitHub (pinned to 89f33cbef2)
Solutions
- Validate length before rotating: if (keys.length !== 48) throw new Error('bad rotation key')
- Generate rotation material with crypto.randomBytes(48) from the same source as initial keys
- Check how the secret store encodes keys (hex doubles the byte count) and decode accordingly
Example fix
// before
server.setTicketKeys(Buffer.from(secretManager.get('ticketKeys'), 'utf8'));
// after
const keys = Buffer.from(secretManager.get('ticketKeys'), 'hex');
if (keys.length === 48) server.setTicketKeys(keys); Defensive patterns
Strategy: validation
Validate before calling
if (keys.length !== 48) throw new RangeError(`ticket keys must be 48 bytes, got ${keys.length}`); Type guard
function isValidRotationKey(v) { return ArrayBuffer.isView(v) && v.byteLength === 48; } Try / catch
try { server.setTicketKeys(keys); } catch (e) { if (/48-byte buffer/.test(e.message)) { /* keep old keys, alert rotation pipeline */ } else throw e; } Prevention
- Unit-test the rotation pipeline asserting exactly 48-byte output
- Use one generator function for initial and rotated keys
When it happens
Trigger: server.setTicketKeys(Buffer.alloc(47)); rotating with a key blob whose hex decoded to 96 bytes (two keys concatenated); rotation pipeline that appends a key-id byte, yielding 49.
Common situations: Automated key rotation where new material is generated with a different length than the original; copying ticket key formats from other TLS stacks that use 32- or 80-byte keys; test fixtures with arbitrary-length buffers.
Related errors
- ERR_INVALID_ARG_VALUE
- fetch failed
- Unsupported 'certFile' / 'keyFile' options provided: use 'ce
- Unsupported 'alpnProtocols' option provided. 'h2' and 'http/
- Both 'cert' and 'key' must be provided to enable HTTPS
AI-assisted analysis of denoland/deno@89f33cbef2 (2026-08-16).
Data as JSON: /api/errors/073b29217aedd865.
Report an issue: GitHub.