{"record":{"id":"072ac3b84918fdc1","repo":"nodejs/node","slug":"und-err-socket-072ac3","errorCode":"UND_ERR_SOCKET","errorMessage":"bad upgrade","messagePattern":"bad upgrade","errorType":"exception","errorClass":"SocketError","httpStatus":null,"severity":"error","filePath":"deps/undici/src/lib/api/api-upgrade.js","lineNumber":50,"sourceCode":"    this.context = null\n\n    addSignal(this, signal)\n  }\n\n  onRequestStart (controller, context) {\n    if (this.reason) {\n      controller.abort(this.reason)\n      return\n    }\n\n    assert(this.callback)\n\n    this.abort = (reason) => controller.abort(reason)\n    this.context = context\n  }\n\n  onResponseStart () {\n    throw new SocketError('bad upgrade', null)\n  }\n\n  onRequestUpgrade (controller, statusCode, headers, socket) {\n    const expectedStatusCode = socket[kHTTP2Stream] === true ? 200 : 101\n\n    if (statusCode !== expectedStatusCode) {\n      const socketInfo = socket[kHTTP2Stream] === true ? null : util.getSocketInfo(socket)\n      controller.abort(new SocketError('bad upgrade', socketInfo))\n      return\n    }\n\n    const { callback, opaque, context } = this\n\n    removeSignal(this)\n\n    this.callback = null\n\n    const rawHeaders = controller?.rawHeaders","sourceCodeStart":32,"sourceCodeEnd":68,"githubUrl":"https://github.com/nodejs/node/blob/1b2de5e052fc0fb95fd7fb6846dcec4ade598e9e/deps/undici/src/lib/api/api-upgrade.js#L32-L68","documentation":"Thrown as a SocketError (code UND_ERR_SOCKET) in two upgrade()-related cases: (1) onResponseStart fires, meaning the server returned a normal HTTP response instead of the expected protocol switch — a hard 'bad upgrade'; (2) onRequestUpgrade receives a status code other than 101 (HTTP/1.1) or 200 (HTTP/2), aborting the controller with this error. It indicates the server did not honor the Upgrade/CONNECT request.","triggerScenarios":"Requesting an upgrade to a server/endpoint that does not support the requested protocol (e.g. WebSocket upgrade against a plain JSON endpoint); missing or wrong Upgrade/Connection headers; server returns 200 with a body instead of 101; HTTP/2 upgrade returning non-200.","commonSituations":"Pointing a WebSocket client at the wrong URL scheme/path; server requires a specific Sec-WebSocket-Key/Subprotocol header that was omitted; reverse proxy/load balancer stripping Upgrade headers; HTTP/2 back-end returning 404/500 during connect.","solutions":["Verify the target server actually supports the protocol you are upgrading to and the URL/path is correct.","Send all required upgrade headers (e.g. Connection: Upgrade, Upgrade: websocket, Sec-WebSocket-Key, Sec-WebSocket-Version: 13).","Check that no proxy/load balancer in the path strips or rewrites the Upgrade/Connection headers.","Wrap the upgrade call in try/catch and fall back to a non-upgraded transport or retry against a known-good endpoint."],"exampleFix":"// before\nclient.upgrade({ path: '/api/data', headers: { Upgrade: 'websocket' } }, cb)\n\n// after\nclient.upgrade({\n  path: '/ws',\n  headers: {\n    Connection: 'Upgrade',\n    Upgrade: 'websocket',\n    'Sec-WebSocket-Key': key,\n    'Sec-WebSocket-Version': '13'\n  }\n}, cb)","handlingStrategy":"try-catch","validationCode":"function buildUpgradeHeaders(protocol) {\n  if (protocol === 'websocket') {\n    return {\n      Connection: 'Upgrade',\n      Upgrade: 'websocket',\n      'Sec-WebSocket-Key': crypto.randomBytes(16).toString('base64'),\n      'Sec-WebSocket-Version': '13'\n    }\n  }\n  return { Connection: 'Upgrade', Upgrade: protocol }\n}\n// client.upgrade({ path: '/ws', headers: buildUpgradeHeaders('websocket') }, cb)","typeGuard":null,"tryCatchPattern":"try {\n  client.upgrade(opts, (err, data) => { if (err) handleBadUpgrade(err); else use(data.socket) })\n} catch (e) {\n  if (e.code === 'UND_ERR_SOCKET' && /bad upgrade/.test(e.message)) {\n    // server did not switch protocols; fall back or surface a clear error\n  } else throw e\n}","preventionTips":["Confirm the server endpoint supports the protocol before attempting an upgrade.","Send the full required header set (Connection, Upgrade, protocol-specific headers).","Ensure no proxy/load balancer strips Upgrade/Connection headers.","Wrap upgrade() in try/catch and handle the SocketError explicitly."],"tags":["undici","upgrade","socket","websocket","protocol","network","runtime"],"backgroundTag":null,"analyzedSha":"1b2de5e052fc0fb95fd7fb6846dcec4ade598e9e","analyzedAt":"2026-08-13T00:53:24.642Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}