{"record":{"id":"5887aa161561ef83","repo":"XTLS/Xray-core","slug":"failed-to-read-auth-methods","errorCode":null,"errorMessage":"failed to read auth methods","messagePattern":"failed to read auth methods","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"proxy/socks/protocol.go","lineNumber":106,"sourceCode":"\t\t\tPort:    port,\n\t\t\tVersion: socks4Version,\n\t\t}\n\t\tif err := writeSocks4Response(writer, socks4RequestGranted, net.AnyIP, net.Port(0)); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\treturn request, nil\n\tdefault:\n\t\twriteSocks4Response(writer, socks4RequestRejected, net.AnyIP, net.Port(0))\n\t\treturn nil, errors.New(\"unsupported command: \", cmd)\n\t}\n}\n\nfunc (s *ServerSession) auth5(nMethod byte, reader io.Reader, writer io.Writer) (username string, err error) {\n\tbuffer := buf.StackNew()\n\tdefer buffer.Release()\n\n\tif _, err = buffer.ReadFullFrom(reader, int32(nMethod)); err != nil {\n\t\treturn \"\", errors.New(\"failed to read auth methods\").Base(err)\n\t}\n\n\tvar expectedAuth byte = authNotRequired\n\tif s.config.AuthType == AuthType_PASSWORD {\n\t\texpectedAuth = authPassword\n\t}\n\n\tif !hasAuthMethod(expectedAuth, buffer.BytesRange(0, int32(nMethod))) {\n\t\twriteSocks5AuthenticationResponse(writer, socks5Version, authNoMatchingMethod)\n\t\treturn \"\", errors.New(\"no matching auth method\")\n\t}\n\n\tif err := writeSocks5AuthenticationResponse(writer, socks5Version, expectedAuth); err != nil {\n\t\treturn \"\", errors.New(\"failed to write auth response\").Base(err)\n\t}\n\n\tif expectedAuth == authPassword {\n\t\tusername, password, err := ReadUsernamePassword(reader)","sourceCodeStart":88,"sourceCodeEnd":124,"githubUrl":"https://github.com/XTLS/Xray-core/blob/7d214f8b094f75322fa3990f8aadad1c912f24f5/proxy/socks/protocol.go#L88-L124","documentation":"Thrown by ServerSession.auth5 (proxy/socks/protocol.go:106) during SOCKS5 method negotiation. The client's first message declares NMETHODS=n but the following read of n method bytes fails (EOF/timeout/reset), i.e. the client under-delivered its declared method list.","triggerScenarios":"Client writes 0x05 0x02 (version + NMETHODS=2) but sends only one method byte or disconnects; a scanner writing a 1-2 byte probe; a client that computed NMETHODS wrongly.","commonSituations":"Hand-rolled SOCKS5 clients with off-by-one NMETHODS; health checks probing the port with junk; middleboxes dropping the tail of small packets; TLS clients connecting to a plain SOCKS port (handshake bytes parse as garbage).","solutions":["Verify the client sends exactly: 0x05, NMETHODS, then NMETHODS bytes, in one write when possible.","Check the base error: EOF = client closed mid-negotiation (client bug or probe); timeout = stalled peer.","Confirm no protocol mismatch (e.g. HTTPS or shadowsocks client pointed at the SOCKS inbound)."],"exampleFix":"// before: NMETHODS says 2 but only 1 method sent\nconn.Write([]byte{0x05, 0x02, 0x00})\n\n// after: NMETHODS matches the list (no-auth + username/password)\nconn.Write([]byte{0x05, 0x02, 0x00, 0x02})","handlingStrategy":"try-catch","validationCode":"// Client-side: NMETHODS must equal the number of method bytes written\nmethods := []byte{0x00, 0x02}\nreq := append([]byte{0x05, byte(len(methods))}, methods...)\nif _, err := conn.Write(req); err != nil {\n    return err\n}","typeGuard":null,"tryCatchPattern":"if err != nil && strings.Contains(err.Error(), \"failed to read auth methods\") {\n    logDebug(\"peer truncated SOCKS5 method negotiation\")\n    conn.Close()\n}","preventionTips":["Send the SOCKS5 greeting (version + NMETHODS + methods) in one write.","Keep NMETHODS consistent with the actual method list length."],"tags":["socks","socks5","protocol","authentication","truncated-request","xray"],"backgroundTag":null,"analyzedSha":"7d214f8b094f75322fa3990f8aadad1c912f24f5","analyzedAt":"2026-08-15T14:26:24.325Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}