{"record":{"id":"ab51debbb8d0b00d","repo":"t8y2/dbx","slug":"zookeeper-gssapi-negotiation-exceeded-d-rounds","errorCode":null,"errorMessage":"ZooKeeper GSSAPI negotiation exceeded %d rounds","messagePattern":"ZooKeeper GSSAPI negotiation exceeded (.+?) rounds","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"agents/drivers/argo-go/zookeeper_protocol.go","lineNumber":229,"sourceCode":"\t\t\treturn fmt.Errorf(\"ZooKeeper SASL round %d: %w\", round+1, requestErr)\n\t\t}\n\t\tdecoder := newZooKeeperDecoder(response)\n\t\tchallenge, decodeErr := decoder.bytes()\n\t\tif decodeErr != nil {\n\t\t\treturn fmt.Errorf(\"decode ZooKeeper SASL round %d: %w\", round+1, decodeErr)\n\t\t}\n\t\tif saslClient.Complete() {\n\t\t\tif len(challenge) != 0 {\n\t\t\t\treturn errors.New(\"ZooKeeper sent an unexpected token after GSSAPI completion\")\n\t\t\t}\n\t\t\treturn nil\n\t\t}\n\t\ttoken, err = saslClient.Step(challenge)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"continue ZooKeeper GSSAPI negotiation at round %d: %w\", round+1, err)\n\t\t}\n\t}\n\treturn fmt.Errorf(\"ZooKeeper GSSAPI negotiation exceeded %d rounds\", zooKeeperMaxSASLRounds)\n}\n\nfunc (client *protocolZooKeeperClient) AddAuth(scheme string, auth []byte) error {\n\t_, err := client.request(zooKeeperOpSetAuth, func(encoder *zooKeeperEncoder) {\n\t\tencoder.int32(0)\n\t\tencoder.string(scheme)\n\t\tencoder.bytes(auth)\n\t})\n\treturn err\n}\n\nfunc (client *protocolZooKeeperClient) Children(path string) ([]string, *zk.Stat, error) {\n\tresponse, err := client.request(zooKeeperOpGetChildren2, func(encoder *zooKeeperEncoder) {\n\t\tencoder.string(path)\n\t\tencoder.boolean(false)\n\t})\n\tif err != nil {\n\t\treturn nil, nil, err","sourceCodeStart":211,"sourceCodeEnd":247,"githubUrl":"https://github.com/t8y2/dbx/blob/c0390bff16418b651f4728520d99adf8ce48829a/agents/drivers/argo-go/zookeeper_protocol.go#L211-L247","documentation":"The SASL/GSSAPI exchange did not complete within the library's hard cap of zooKeeperMaxSASLRounds (8) request/response round trips, so authenticateSASL aborts to prevent an infinite loop. A legitimate Kerberos handshake finishes in 2-4 legs; exceeding 8 rounds means the server keeps challenging without ever signaling context completion, typically because authentication is being rejected or a non-GSSAPI peer is on the other end.","triggerScenarios":"authenticateSASL loops the full 8 iterations with saslClient.Complete() never returning true and Step never erroring — the server persistently replies with challenges that the local GSSAPI mechanism keeps answering (e.g. server not actually performing SASL auth, echoing tokens, or an auth failure that surfaces as another challenge instead of an error).","commonSituations":"Pointing the client at a ZooKeeper server (or wrong port, e.g. a different service) that does not have SASL enabled while the client attempts GSSAPI, server/client mechanism mismatch (server expects DIGEST-MD5 while client runs GSSAPI), or a mid-handshake auth failure the server reports as a continued challenge.","solutions":["Verify the ZooKeeper server has SASL authentication enabled and expects GSSAPI (check jaas.conf, authProvider config, and server logs for 'SASL authentication failed' entries).","Confirm you are connecting to port 2181 of an actual ZooKeeper member, not another service or a misplaced proxy.","Compare the client mechanism with the server's configured mechanism (GSSAPI vs DIGEST-MD5) and align JAAS/krb5 configuration on both sides.","Check server logs during connection: an auth failure being replayed as a challenge is the usual cause; fix the underlying credential/principal problem.","If your Kerberos setup legitimately requires more legs (rare, multi-hop), the cap is fixed at 8 in this driver — reduce handshake complexity (single-hop realm)."],"exampleFix":"// before: server without SASL configured\nhosts := \"zk-nosasl.internal:2181\" // negotiation exceeds 8 rounds\n// after: point at SASL-enabled quorum (server jaas.conf with QuorumServer/Server sections)\nhosts := \"zk-sasl-1.internal:2181,zk-sasl-2.internal:2181\"","handlingStrategy":"validation","validationCode":"// Before connecting, confirm the endpoint is a SASL-capable ZooKeeper\nconn, err := net.DialTimeout(\"tcp\", \"zk-host:2181\", 3*time.Second)\nif err != nil {\n    return err\n}\nconn.Close()\n// and verify server config out-of-band (4lw 'srvr' or admin API) shows auth_enabled / sasl.enabled","typeGuard":null,"tryCatchPattern":"if err := client.Connect(); err != nil {\n    if strings.Contains(err.Error(), \"exceeded 8 rounds\") {\n        return fmt.Errorf(\"server likely has SASL disabled or mechanism mismatch; check server jaas.conf and port: %w\", err)\n    }\n    return err\n}","preventionTips":["Confirm SASL is enabled on the target ZooKeeper ensemble before enabling it on the client.","Match the SASL mechanism (GSSAPI) on both client and server configuration.","Double-check the port and host — a non-ZooKeeper service on 2181 produces endless challenge loops.","Review server logs during connection attempts to catch auth failures masquerading as repeated challenges."],"tags":["go","zookeeper","sasl","kerberos","gssapi","protocol"],"backgroundTag":"sasl-handshake-failed","analyzedSha":"c0390bff16418b651f4728520d99adf8ce48829a","analyzedAt":"2026-09-05T23:05:10.900Z","contentChangedAt":"2026-09-05T23:05:10.900Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}