nodejs/node · error · Socks5ProxyError

UND_ERR_SOCKS5_AUTH_FAILED

UND_ERR_SOCKS5_AUTH_FAILED

Error message

Authentication failed

What it means

Thrown in handleAuthResponse() when the STATUS byte of the auth reply is non-zero. Per RFC 1929, STATUS=0x00 means success; any other value means authentication failed (bad credentials). This is the proxy actively rejecting the username/password.

Solutions

  1. Verify the username and password against the proxy's configured credentials.
  2. Trim whitespace and check for accidental newlines in credential strings.
  3. If credentials come from a URL, ensure percent-encoding is decoded correctly.
  4. Re-test with curl --socks5-hostname user:pass@host to isolate the client from the credentials.

Example fix

// before
username: process.env.PROXY_USER,
password: 'pass\n'  // trailing newline

// after
username: process.env.PROXY_USER?.trim(),
password: process.env.PROXY_PASS?.trim()
Defensive patterns

Strategy: retry

Validate before calling

function cleanCred(v) {
  if (typeof v !== 'string') throw new Error('credential missing')
  const trimmed = v.trim()
  if (trimmed.length === 0) throw new Error('credential empty')
  return trimmed
}

Try / catch

try { client.handshake() } catch (e) {
  if (e.code === 'UND_ERR_SOCKS5_AUTH_FAILED') { /* verify/refresh credentials, then retry on a new client */ }
  else throw e
}

Prevention

When it happens

Trigger: Wrong username or password; expired or rotated credentials; credentials for a different realm/account; trailing whitespace or encoding issues in the credential strings.

Common situations: Typo in env var values; copy-paste introduced a newline; secrets rotated server-side but not in the client; URL-encoded credentials not decoded from the proxy URL.

Understand the failure class

Related errors


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

Appendix: source

Thrown at deps/undici/src/lib/core/socks5-client.js:262

  }

  /**
   * Handle authentication response
   */
  handleAuthResponse () {
    if (this.buffer.length < 2) {
      return // Not enough data yet
    }

    const version = this.buffer[0]
    const status = this.buffer[1]

    if (version !== 0x01) {
      throw new Socks5ProxyError(`Invalid auth sub-negotiation version: ${version}`, 'UND_ERR_SOCKS5_AUTH_VERSION')
    }

    if (status !== 0x00) {
      throw new Socks5ProxyError('Authentication failed', 'UND_ERR_SOCKS5_AUTH_FAILED')
    }

    this.buffer = this.buffer.subarray(2)
    debug('authentication successful')
    this.markAuthenticated()
  }

  /**
   * Send CONNECT command
   * @param {string} address - Target address (IP or domain)
   * @param {number} port - Target port
   */
  connect (address, port) {
    if (this.state === STATES.CONNECTING || this.state === STATES.CONNECTED) {
      throw new InvalidArgumentError('Connection already in progress')
    }

    if (this.state !== STATES.AUTHENTICATED) {

View on GitHub (pinned to 1b2de5e052)