nodejs/node · error · Socks5ProxyError
UND_ERR_SOCKS5_REPLY_VERSION
UND_ERR_SOCKS5_REPLY_VERSION
Error message
Invalid SOCKS version in reply: ${version} What it means
Thrown in handleConnectResponse() when the VER byte of the CONNECT reply is not SOCKS_VERSION (0x05). Like the handshake version check, this catches a non-SOCKS5 or desynchronized reply at the final CONNECT stage.
Source
Thrown at deps/undici/src/lib/core/socks5-client.js:328
request.writeUInt16BE(port, 4 + addressBuffer.length)
return request
}
/**
* Handle CONNECT response
*/
handleConnectResponse () {
if (this.buffer.length < 4) {
return // Not enough data for header
}
const version = this.buffer[0]
const reply = this.buffer[1]
const addressType = this.buffer[3]
if (version !== SOCKS_VERSION) {
throw new Socks5ProxyError(`Invalid SOCKS version in reply: ${version}`, 'UND_ERR_SOCKS5_REPLY_VERSION')
}
// Calculate the expected response length
let responseLength = 4 // VER + REP + RSV + ATYP
if (addressType === ADDRESS_TYPES.IPV4) {
responseLength += 4 + 2 // IPv4 + port
} else if (addressType === ADDRESS_TYPES.DOMAIN) {
if (this.buffer.length < 5) {
return // Need domain length byte
}
responseLength += 1 + this.buffer[4] + 2 // length byte + domain + port
} else if (addressType === ADDRESS_TYPES.IPV6) {
responseLength += 16 + 2 // IPv6 + port
} else {
throw new Socks5ProxyError(`Invalid address type in reply: ${addressType}`, 'UND_ERR_SOCKS5_ADDR_TYPE')
}
if (this.buffer.length < responseLength) {View on GitHub (pinned to 1b2de5e052)
Solutions
- Ensure the auth/handshake replies were fully consumed so this.buffer starts at the CONNECT reply.
- Reconnect on a fresh socket to clear desync.
- Capture the byte stream to confirm the server's CONNECT reply format.
- Test against a reference SOCKS5 server to rule out client-side framing.
Example fix
// no caller config fixes a desync/non-conformant reply; // reset state with a fresh client + socket: // socket.destroy(); client = new Socks5Client(newSocket, opts); client.handshake();
Defensive patterns
Strategy: try-catch
Try / catch
try { /* wait for connect response */ } catch (e) {
if (e.code === 'UND_ERR_SOCKS5_REPLY_VERSION') {
// desync or non-conformant server; reconnect on a fresh socket
} else throw e
} Prevention
- Fully consume each reply so this.buffer starts at the next frame.
- Reconnect fresh after any protocol desync.
- Capture a trace to confirm the server's CONNECT reply VER byte.
When it happens
Trigger: Server sends a reply without the VER byte; buffer desync leaves bytes from the auth reply still in this.buffer; the endpoint behind the proxy is not SOCKS5-compliant; a MITM injects non-SOCKS data.
Common situations: Framing bug where prior reply bytes were not fully consumed; buggy server omitting VER; reconnect over a corrupted socket.
Related errors
- UND_ERR_SOCKS5_VERSION
- UND_ERR_SOCKS5_ADDR_TYPE
- UND_ERR_SOCKET
- UND_ERR_SOCKS5_AUTH_REJECTED
- UND_ERR_SOCKS5_AUTH_METHOD
AI-assisted analysis of nodejs/node@1b2de5e052 (2026-08-13).
Data as JSON: /api/errors/563743bee0e3584b.
Report an issue: GitHub.