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

  1. Ensure the auth/handshake replies were fully consumed so this.buffer starts at the CONNECT reply.
  2. Reconnect on a fresh socket to clear desync.
  3. Capture the byte stream to confirm the server's CONNECT reply format.
  4. 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

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


AI-assisted analysis of nodejs/node@1b2de5e052 (2026-08-13). Data as JSON: /api/errors/563743bee0e3584b. Report an issue: GitHub.