{"record":{"id":"0753f7f34996ccec","repo":"denoland/deno","slug":"err-tls-sni-from-server","errorCode":"ERR_TLS_SNI_FROM_SERVER","errorMessage":"Cannot issue SNI from a TLS server-side socket","messagePattern":"Cannot issue SNI from a TLS server-side socket","errorType":"error_code","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"ext/node/polyfills/_tls_wrap.js","lineNumber":1065,"sourceCode":"    tcpHandle.readStart();\n  }\n\n  // Kick-start the TLS readable side. During start(), the handshake cycle\n  // may have received and processed a close_notify (peer called end() before\n  // we set up event listeners). The decrypted EOF is buffered in pending_eof\n  // because inner.onread wasn't set yet. Call readStart() directly on the\n  // TLSWrap to install onread and flush any pending data/EOF.\n  if (this._handle) {\n    this._handle.readStart();\n  }\n};\n\nTLSSocket.prototype.setServername = function (name) {\n  if (typeof name !== \"string\") {\n    throw new ERR_INVALID_ARG_TYPE(\"name\", \"string\", name);\n  }\n  if (this._tlsOptions?.isServer) {\n    throw new ERR_TLS_SNI_FROM_SERVER();\n  }\n  this._handle?.setServername(name);\n};\n\n// Format prefixes for the synthetic session buffers we emit from\n// onConnectSecure when rustls handles resumption internally. The encoded\n// payload is `${servername ?? host ?? \"\"}:${port ?? \"\"}` -- see the\n// matching emit sites in onConnectSecure.\nconst SYNTHETIC_SESSION_PREFIXES = [\n  \"deno-tls12-session:\",\n  \"deno-tls13-session-ticket-1:\",\n  \"deno-tls13-session-ticket-2:\",\n  \"deno-tls13-dummy-session:\",\n];\n\nfunction syntheticSessionMatches(buf, options) {\n  if (!buf || !options) return false;\n  const sessionKey = `${options.servername ?? options.host ?? \"\"}:${","sourceCodeStart":1047,"sourceCodeEnd":1083,"githubUrl":"https://github.com/denoland/deno/blob/89f33cbef296a2b287f323d42de54c871fa69c77/ext/node/polyfills/_tls_wrap.js#L1047-L1083","documentation":"TLS Server Name Indication is sent only by clients; a server never names itself. TLSSocket.prototype.setServername throws ERR_TLS_SNI_FROM_SERVER (ext/node/polyfills/_tls_wrap.js:1065) when called on a socket created with _tlsOptions.isServer — i.e. a socket accepted by a tls.Server. The check mirrors Node.js exactly.","triggerScenarios":"Inside a tls.createServer connection handler, calling socket.setServername(...) on the accepted TLSSocket; sharing a setServername call path between client and server sockets without checking socket._tlsOptions.isServer.","commonSituations":"Generic TLS wrapper libraries that apply the same configuration function to both outbound (connect) and inbound (accept) sockets; code copied from a client example reused in a server; attempting to mutate SNI after the handshake on the server side.","solutions":["Only call setServername on client sockets created via tls.connect(), never on sockets passed to tls.createServer's connection callback","Branch on the socket role before configuring: if (!socket._tlsOptions?.isServer) socket.setServername(name)","On the server side, select certificates per-SNI via server.addContext(servername, ctx) or the SNICallback option instead"],"exampleFix":"// before\nconst server = tls.createServer(opts, (socket) => {\n  socket.setServername('example.com'); // ERR_TLS_SNI_FROM_SERVER\n});\n\n// after\nconst server = tls.createServer({\n  ...opts,\n  SNICallback: (servername, cb) => cb(null, ctxFor(servername)),\n});","handlingStrategy":"validation","validationCode":"if (socket._tlsOptions?.isServer) throw new Error('cannot set SNI on a server-side socket');","typeGuard":"function isClientTls(socket) { return socket?._tlsOptions?.isServer !== true; }","tryCatchPattern":"try { socket.setServername(name); } catch (e) { if (e.code === 'ERR_TLS_SNI_FROM_SERVER') { /* configure SNI via SNICallback instead */ } else throw e; }","preventionTips":["Use SNICallback/addContext on servers; setServername only on tls.connect sockets","Keep client and server socket configuration code in separate functions"],"tags":["tls","sni","server","misuse"],"backgroundTag":null,"analyzedSha":"89f33cbef296a2b287f323d42de54c871fa69c77","analyzedAt":"2026-08-16T07:54:21.310Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}