This error occurs when a TLS client attempts to use session resumption via session tickets, but the server has explicitly disabled this feature through the SSL_OP_NO_TICKET flag. Session tickets are a performance optimization that allows clients to resume previous TLS sessions without a full handshake.
The ERR_TLS_SESSION_TICKET_APP_DISABLED error indicates that the Node.js TLS/HTTPS server has been configured to disable session tickets through the secureOptions parameter. Session tickets are a TLS extension that allows clients to resume previous sessions by storing encrypted session state on the client side, avoiding the need for server-side session caching. When a server disables session tickets using the SSL_OP_NO_TICKET flag, clients that attempt to use a previously issued session ticket will encounter this error because the server refuses to accept ticket-based resumption. This configuration is often intentional, used in scenarios where session ticket management becomes problematic (such as in clustered environments without shared ticket keys) or where security policies prohibit session tickets due to key rotation concerns.
Check if your TLS server is explicitly disabling session tickets:
const tls = require('tls');
const constants = require('node:constants');
// Check if SSL_OP_NO_TICKET is set
const server = tls.createServer({
key: fs.readFileSync('server-key.pem'),
cert: fs.readFileSync('server-cert.pem'),
secureOptions: constants.SSL_OP_NO_TICKET // <-- This disables tickets
}, (socket) => {
console.log('server connected');
});Look for SSL_OP_NO_TICKET in your secureOptions configuration.
If session tickets are desired and you're running a single-server application, remove the flag:
const tls = require('tls');
const fs = require('fs');
const server = tls.createServer({
key: fs.readFileSync('server-key.pem'),
cert: fs.readFileSync('server-cert.pem'),
// Remove or don't set secureOptions with SSL_OP_NO_TICKET
}, (socket) => {
console.log('server connected');
});
server.listen(8000, () => {
console.log('TLS server listening on port 8000');
});Session tickets are enabled by default in Node.js TLS servers.
If running in cluster mode, synchronize ticket keys across all workers:
const cluster = require('cluster');
const tls = require('tls');
const crypto = require('crypto');
const fs = require('fs');
if (cluster.isMaster) {
// Generate shared ticket keys (48 bytes)
const ticketKeys = crypto.randomBytes(48);
// Save to shared location or pass via IPC
fs.writeFileSync('/tmp/ticket-keys.bin', ticketKeys);
// Fork workers
for (let i = 0; i < 4; i++) {
cluster.fork();
}
} else {
// Workers read the shared keys
const ticketKeys = fs.readFileSync('/tmp/ticket-keys.bin');
const server = tls.createServer({
key: fs.readFileSync('server-key.pem'),
cert: fs.readFileSync('server-cert.pem'),
ticketKeys: ticketKeys // Share same keys across workers
}, (socket) => {
console.log('Worker', process.pid, 'accepted connection');
});
server.listen(8000);
}This ensures all workers can decrypt tickets issued by any worker.
For production environments, rotate ticket keys periodically:
const tls = require('tls');
const crypto = require('crypto');
const server = tls.createServer({
key: fs.readFileSync('server-key.pem'),
cert: fs.readFileSync('server-cert.pem'),
});
// Rotate keys every 24 hours
setInterval(() => {
const newKeys = crypto.randomBytes(48);
server.setTicketKeys(newKeys);
console.log('Ticket keys rotated');
}, 24 * 60 * 60 * 1000);
server.listen(8000);Store and synchronize these keys across all server instances in load-balanced setups.
Configure session timeout to control how long tickets remain valid:
const tls = require('tls');
const server = tls.createServer({
key: fs.readFileSync('server-key.pem'),
cert: fs.readFileSync('server-cert.pem'),
sessionTimeout: 300 // 5 minutes (in seconds)
}, (socket) => {
console.log('Connection established');
});
server.listen(8000);Both session identifiers and session tickets will timeout after this duration.
Security Considerations:
Session ticket keys are cryptographic keys and must be stored securely. With TLS 1.2 and below, if ticket keys are compromised, all sessions that used tickets encrypted with them can be decrypted. Never store these keys on disk in production environments without proper encryption, and regenerate them regularly.
Load Balancer Configurations:
To use session tickets across server restarts or load balancers, all servers must share the same ticket keys. The TLS module exposes three 16-byte keys internally as a single 48-byte Buffer for convenience. Distribute this buffer securely to all server instances.
Cluster Mode Without Shared Keys:
In cluster mode, each worker initializes SSL_CTX_new with random ticket values. Without synchronization, workers cannot decrypt tickets issued by other workers, effectively breaking session resumption. The workaround is either to use SSL_OP_NO_TICKET to disable tickets entirely or implement shared key distribution as shown above.
TLS 1.3 Differences:
TLS 1.3 uses a different mechanism for session resumption (PSK - Pre-Shared Keys) which provides forward secrecy even if the ticket encryption key is compromised. Node.js supports TLS 1.3 session resumption with improved security characteristics.
Performance Impact:
Disabling session tickets forces full TLS handshakes on every connection, increasing CPU usage and latency. However, in certain security-sensitive environments or when proper key management is infeasible, the performance trade-off may be acceptable.
Error: Listener already called (once event already fired)
EventEmitter listener already called with once()
Error: EACCES: permission denied, open '/root/file.txt'
EACCES: permission denied
Error: Invalid encoding specified (stream encoding not supported)
How to fix Invalid encoding error in Node.js readable streams
Error: EINVAL: invalid argument, open
EINVAL: invalid argument, open
TypeError: readableLength must be a positive integer (stream config)
TypeError: readableLength must be a positive integer in Node.js streams