nodejs/node · error · SocketError
UND_ERR_SOCKET
UND_ERR_SOCKET
Error message
bad connect
What it means
Thrown as a SocketError (code UND_ERR_SOCKET) by ConnectHandler.onResponseStart. undici.connect issues an HTTP CONNECT request expecting a 101 Switching Protocols upgrade (handled by onRequestUpgrade). If the server responds with a normal HTTP response instead of an upgrade, onResponseStart fires and undici throws 'bad connect' — the tunnel was never established. This is a protocol/server-level failure, not an argument error.
Source
Thrown at deps/undici/src/lib/api/api-connect.js:48
this.abort = null
addSignal(this, signal)
}
onRequestStart (controller, context) {
if (this.reason) {
controller.abort(this.reason)
return
}
assert(this.callback)
this.abort = (reason) => controller.abort(reason)
this.context = context
}
onResponseStart () {
throw new SocketError('bad connect', null)
}
onRequestUpgrade (controller, statusCode, headers, socket) {
const { callback, opaque, context } = this
removeSignal(this)
this.callback = null
let responseHeaders = headers
const rawHeaders = controller?.rawHeaders
// Indicates is an HTTP2Session
if (responseHeaders != null) {
responseHeaders = this.responseHeaders === 'raw'
? util.parseRawHeaders(rawHeaders)
: headers
}
View on GitHub (pinned to 1b2de5e052)
Solutions
- Point connect() at an HTTP proxy that supports CONNECT, not directly at the origin server.
- If a proxy is required, authenticate via Proxy-Authorization or configure allowlisting on the proxy.
- For raw TLS to an origin, use undici request/stream with an https URL or a dedicated Client instead of connect().
- Inspect the response status/headers from the intermediary to diagnose the refused tunnel.
Example fix
// before: connecting directly to origin (no CONNECT support)
undici.connect({ path: 'api.example.com:443' }, cb) // server returns 200 -> 'bad connect'
// after: tunnel through a CONNECT-capable proxy
undici.connect({ path: 'api.example.com:443', dispatcher: new undici.ProxyAgent('http://proxy:3128') }, cb) Defensive patterns
Strategy: try-catch
Try / catch
undici.connect({ path: target, dispatcher: proxyAgent }, (err, { socket }) => {
if (err && err.code === 'UND_ERR_SOCKET' && /bad connect/.test(err.message)) {
console.error('CONNECT rejected by upstream — point connect() at a CONNECT-capable proxy')
return
}
if (err) throw err
// use socket
}) Prevention
- Use connect() only against CONNECT-capable HTTP proxies.
- For raw TLS to an origin, use undici.Client/request with an https URL instead of connect().
- Ensure proxy auth and allowlisting are configured.
- Inspect intermediary responses (407/403) before retrying.
When it happens
Trigger: Calling undici.connect against a target that does not support CONNECT tunneling: the upstream returned a regular HTTP response (200/4xx/5xx) instead of a 101 upgrade. Common when connecting directly to an origin server (not a proxy), or when a proxy refuses the CONNECT (e.g. 407 auth required, 403 forbidden).
Common situations: Using connect() as if it were a raw TCP socket to an origin (it requires a proxy that speaks CONNECT); proxy requires auth/allowlist not configured; TLS origin rejecting CONNECT; intermediary (corporate proxy/firewall) returning an HTML error page.
Related errors
- UND_ERR_SOCKET
- UND_ERR_INVALID_ARG
- UND_ERR_SOCKS5_VERSION
- UND_ERR_SOCKS5_REPLY_VERSION
- UND_ERR_SOCKS5_ADDR_TYPE
AI-assisted analysis of nodejs/node@1b2de5e052 (2026-08-13).
Data as JSON: /api/errors/b69998f19590fcd0.
Report an issue: GitHub.