t8y2/dbx · error
ZooKeeper SASL token is truncated
Error message
ZooKeeper SASL token is truncated
What it means
After a successful (error code 0) SASL response header, the 4-byte token length field is expected at bytes 20-24. If the frame ends there, the response carries no token body, which the protocol requires, so the driver rejects it as truncated.
Source
Thrown at agents/drivers/zookeeper/sasl.go:144
return nil, err
}
response, err := readZooKeeperFrame(connection)
if err != nil {
return nil, err
}
if len(response) < 20 {
return nil, errors.New("ZooKeeper SASL response is truncated")
}
responseXID := int32(binary.BigEndian.Uint32(response[4:8]))
if responseXID != xid {
return nil, fmt.Errorf("ZooKeeper SASL response xid %d does not match request xid %d", responseXID, xid)
}
errorCode := int32(binary.BigEndian.Uint32(response[16:20]))
if errorCode != 0 {
return nil, fmt.Errorf("ZooKeeper SASL server returned error %d", errorCode)
}
if len(response) < 24 {
return nil, errors.New("ZooKeeper SASL token is truncated")
}
tokenLength := int(int32(binary.BigEndian.Uint32(response[20:24])))
if tokenLength < 0 || tokenLength > zooKeeperMaximumFrameLen || 24+tokenLength > len(response) {
return nil, fmt.Errorf("ZooKeeper SASL token length %d is invalid", tokenLength)
}
return append([]byte(nil), response[24:24+tokenLength]...), nil
}
func readZooKeeperFrame(reader io.Reader) ([]byte, error) {
header := make([]byte, 4)
if _, err := io.ReadFull(reader, header); err != nil {
return nil, err
}
length := int(int32(binary.BigEndian.Uint32(header)))
if length < 0 || length > zooKeeperMaximumFrameLen {
return nil, fmt.Errorf("ZooKeeper frame length %d is invalid", length)
}
payload := make([]byte, length+4)View on GitHub (pinned to c0390bff16)
Solutions
- Capture the raw frame and compare with a standard ZooKeeper SASL handshake
- Check for intermediaries (proxies, TLS terminators) mangling the stream
- Retry authentication; if reproducible, verify the server's SASL provider emits a token on success
- Update the ZooKeeper server or driver versions
Defensive patterns
Strategy: try-catch
Try / catch
token, err := zooKeeperSASLRound(conn, xid, challenge)
if err != nil {
if strings.Contains(err.Error(), "token is truncated") {
// capture/inspect raw frame, reconnect, and report server-side issue
}
return err
} Prevention
- Keep client and server on compatible ZooKeeper versions
- Bypass or correctly configure TLS-terminating proxies
- Add packet-level logging when enabling SASL for the first time
- Retry once on truncation before escalating to auth failure
When it happens
Trigger: The SASL response frame is at least 20 bytes (header OK, errorCode 0) but shorter than 24 bytes, so the token length field itself is missing.
Common situations: Server bug sending an empty SASL completion, a man-in-the-middle/proxy stripping payload bytes, or a custom server build with malformed SASL replies.
Related errors
- ZooKeeper sent an unexpected token after GSSAPI completion
- ZooKeeper sent an unexpected token after GSSAPI completion
- ZooKeeper sent an unexpected token after DIGEST-MD5 completi
- ZooKeeper DIGEST-MD5 completed with an unexpected client tok
- ZooKeeper SASL response is truncated
AI-assisted analysis of t8y2/dbx@c0390bff16 (2026-09-05).
Data as JSON: /api/errors/3d844ff04dafd7f4.
Report an issue: GitHub.