XTLS/Xray-core · error

failed to read username and password for authentication

Error message

failed to read username and password for authentication

What it means

Thrown in auth5 (proxy/socks/protocol.go:126) when ReadUsernamePassword fails parsing the RFC 1929 sub-negotiation message: 0x01, ULEN, username(ULEN), PLEN, password(PLEN). Any short read, bad length prefix, or connection drop during this message triggers it.

Source

Thrown at proxy/socks/protocol.go:126

	var expectedAuth byte = authNotRequired
	if s.config.AuthType == AuthType_PASSWORD {
		expectedAuth = authPassword
	}

	if !hasAuthMethod(expectedAuth, buffer.BytesRange(0, int32(nMethod))) {
		writeSocks5AuthenticationResponse(writer, socks5Version, authNoMatchingMethod)
		return "", errors.New("no matching auth method")
	}

	if err := writeSocks5AuthenticationResponse(writer, socks5Version, expectedAuth); err != nil {
		return "", errors.New("failed to write auth response").Base(err)
	}

	if expectedAuth == authPassword {
		username, password, err := ReadUsernamePassword(reader)
		if err != nil {
			return "", errors.New("failed to read username and password for authentication").Base(err)
		}

		if !s.config.HasAccount(username, password) {
			writeSocks5AuthenticationResponse(writer, 0x01, 0xFF)
			return "", errors.New("invalid username or password")
		}

		if err := writeSocks5AuthenticationResponse(writer, 0x01, 0x00); err != nil {
			return "", errors.New("failed to write auth response").Base(err)
		}
		return username, nil
	}

	return "", nil
}

func (s *ServerSession) handshake5(nMethod byte, reader io.Reader, writer net.Conn) (*protocol.RequestHeader, *TempUDPConn, error) {
	var (

View on GitHub (pinned to 7d214f8b09)

Solutions

  1. Verify the client encodes RFC 1929 exactly: 0x01 | ULEN(1) | UNAME(ULEN) | PLEN(1) | PASSWD(PLEN), each length <= 255.
  2. Shorten credentials to at most 255 bytes each; the protocol cannot carry longer ones.
  3. Check the base error for EOF/reset to distinguish framing bugs from dropped connections.

Example fix

// before: forgot PLEN/PASSWD section
conn.Write([]byte{0x01, 0x05, 'a','l','i','c','e'})

// after: full RFC1929 message, user=alice pass=secret
conn.Write([]byte{0x01, 0x05, 'a','l','i','c','e', 0x06, 's','e','c','r','e','t'})
Defensive patterns

Strategy: validation

Validate before calling

// Client-side: build a spec-compliant RFC 1929 message
func rfc1929(user, pass string) ([]byte, error) {
    if len(user) == 0 || len(user) > 255 || len(pass) > 255 {
        return nil, fmt.Errorf("credentials exceed RFC1929 1-byte length limits")
    }
    msg := []byte{0x01, byte(len(user))}
    msg = append(msg, user...)
    msg = append(msg, byte(len(pass)))
    return append(msg, pass...), nil
}

Try / catch

if err != nil && strings.Contains(err.Error(), "failed to read username and password") {
    return fmt.Errorf("malformed RFC1929 credentials message: %w", err)
}

Prevention

When it happens

Trigger: Client offers method 0x02 but sends a malformed username/password message: wrong version byte handled by the reader, ULEN larger than the actual data, missing password section, or disconnect mid-message.

Common situations: Custom clients with wrong length encoding; usernames or passwords over 255 bytes (the 1-byte length field cannot represent them); connections cut during slow handshakes; proxy chains where an intermediate mangles the stream.

Understand the failure class

Related errors


AI-assisted analysis of XTLS/Xray-core@7d214f8b09 (2026-08-15). Data as JSON: /api/errors/287b42c9e46fdc32. Report an issue: GitHub.