t8y2/dbx · error

ZooKeeper sent an unexpected token after GSSAPI completion

Error message

ZooKeeper sent an unexpected token after GSSAPI completion

What it means

During authenticateSASL, once the local GSSAPI client reports Complete(), the server must send no further SASL token. If an additional non-empty challenge arrives after completion, the protocol state is inconsistent and the client returns this error rather than feeding the completed negotiator another token.

Source

Thrown at agents/drivers/argo-go/zookeeper_protocol.go:220

	for round := 0; round < zooKeeperMaxSASLRounds; round++ {
		response, requestErr := client.request(zooKeeperOpSASL, func(encoder *zooKeeperEncoder) {
			if token == nil {
				encoder.bytes([]byte{})
				return
			}
			encoder.bytes(token)
		})
		if requestErr != nil {
			return fmt.Errorf("ZooKeeper SASL round %d: %w", round+1, requestErr)
		}
		decoder := newZooKeeperDecoder(response)
		challenge, decodeErr := decoder.bytes()
		if decodeErr != nil {
			return fmt.Errorf("decode ZooKeeper SASL round %d: %w", round+1, decodeErr)
		}
		if saslClient.Complete() {
			if len(challenge) != 0 {
				return errors.New("ZooKeeper sent an unexpected token after GSSAPI completion")
			}
			return nil
		}
		token, err = saslClient.Step(challenge)
		if err != nil {
			return fmt.Errorf("continue ZooKeeper GSSAPI negotiation at round %d: %w", round+1, err)
		}
	}
	return fmt.Errorf("ZooKeeper GSSAPI negotiation exceeded %d rounds", zooKeeperMaxSASLRounds)
}

func (client *protocolZooKeeperClient) AddAuth(scheme string, auth []byte) error {
	_, err := client.request(zooKeeperOpSetAuth, func(encoder *zooKeeperEncoder) {
		encoder.int32(0)
		encoder.string(scheme)
		encoder.bytes(auth)
	})
	return err

View on GitHub (pinned to c0390bff16)

Solutions

  1. Verify you are connecting directly to a supported ZooKeeper version and not through a packet-rewriting proxy
  2. Ensure client and server SASL configurations match (quorum.auth / server.auth settings)
  3. Capture the exchange (packet logs) and check whether the extra token is a duplicated frame
  4. Retry the connection — a transient desync in one session may not recur; if persistent, align server/client versions
Defensive patterns

Strategy: retry

Validate before calling

// no caller-side check; ensure direct connectivity to a supported ZooKeeper version
if viaProxy {
    log.Warn("SASL through proxies can produce extra tokens; connect directly if possible")
}

Try / catch

err := zkClient.authenticateSASL(sasl)
if err != nil && strings.Contains(err.Error(), "unexpected token after GSSAPI completion") {
    // retry once with a fresh connection; if persistent, audit server/proxy SASL config
}

Prevention

When it happens

Trigger: A misbehaving or non-conformant ZooKeeper server (or a proxy/interposer) sends an extra SASL challenge after the GSSAPI exchange finished; decoding a stale/duplicated SASL response frame; protocol version mismatch causing frame desynchronization.

Common situations: Connecting through a load balancer or proxy that replays buffered packets; ZooKeeper server versions with buggy SASL handling; mixed client/server SASL quorum settings causing spurious rounds.

Understand the failure class

Related errors


AI-assisted analysis of t8y2/dbx@c0390bff16 (2026-09-05). Data as JSON: /api/errors/06f18c79346175da. Report an issue: GitHub.