t8y2/dbx · error

start ZooKeeper GSSAPI negotiation: %w

Error message

start ZooKeeper GSSAPI negotiation: %w

What it means

During SASL authentication, authenticateSASL calls saslClient.Start() to obtain the initial GSSAPI token; if the Kerberos/GSSAPI layer cannot begin the exchange (missing credentials, bad principal, no ticket), the error is wrapped as 'start ZooKeeper GSSAPI negotiation'. The SASL client is disposed on exit, and no SASL rounds are attempted when Start fails.

Source

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

func zooKeeperTimeoutMillis(timeout time.Duration) int32 {
	milliseconds := timeout.Milliseconds()
	if milliseconds < 1 {
		return 1
	}
	if milliseconds > math.MaxInt32 {
		return math.MaxInt32
	}
	return int32(milliseconds)
}

func (client *protocolZooKeeperClient) authenticateSASL(saslClient zooKeeperSASLClient) error {
	if saslClient == nil {
		return errors.New("ZooKeeper SASL client is nil")
	}
	defer saslClient.Dispose()
	token, err := saslClient.Start()
	if err != nil {
		return fmt.Errorf("start ZooKeeper GSSAPI negotiation: %w", err)
	}
	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() {

View on GitHub (pinned to c0390bff16)

Solutions

  1. Run klist to confirm a valid, unexpired TGT; re-run kinit or refresh the keytab-based login
  2. Verify the client principal and target service principal (zookeeper/host@REALM) and krb5.conf KDC settings
  3. Ensure krb5.conf and the keytab are present and readable inside the container/pod
  4. Check clock skew against the KDC (tickets fail with skew > ~5 minutes)
  5. Enable GSSAPI/JAAS debug logging (-Dsun.security.krb5.debug=true) to see the exact Kerberos failure

Example fix

// before (container startup, no credentials)
CMD ["/app/server"]
// after
CMD ["kinit -kt /etc/krb5/zkclient.keytab zkclient@EXAMPLE.COM && /app/server"]
Defensive patterns

Strategy: try-catch

Validate before calling

func hasKerberosTicket() error {
    // e.g. probe a fresh GSSAPI login before attempting the SASL handshake
    cli, err := newSASLClient(service, host)
    if err != nil { return fmt.Errorf("GSSAPI init failed (kinit?): %w", err) }
    cli.Dispose()
    return nil
}

Try / catch

err := client.authenticateSASL(saslClient)
if err != nil {
    var gerr *gsasl.Error
    if strings.Contains(err.Error(), "start ZooKeeper GSSAPI negotiation") {
        // credentials problem: refresh ticket, then retry once
        if rerr := refreshKeytabLogin(); rerr == nil {
            err = client.authenticateSASL(newSASLClient(service, host))
        }
    }
    return err
}

Prevention

When it happens

Trigger: authenticateSASL invoked (from newProtocolZooKeeperClient's auth flow after connect) when saslClient.Start() errors: no valid Kerberos TGT, wrong service principal for the ZooKeeper server, keytab/JAAS misconfiguration, or GSSAPI library initialization failure.

Common situations: Expired or missing kinit ticket in a long-running service; Kerberos realm/KDC unreachable from the container; service principal mismatch (zkclient/... vs zookeeper/... or cross-realm issues); krb5.conf not mounted into the pod; clock skew invalidating tickets.

Related errors


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