t8y2/dbx · error
ZooKeeper response frame is %d bytes, maximum is %d
Error message
ZooKeeper response frame is %d bytes, maximum is %d
What it means
readFrame reads the 4-byte big-endian length header of a ZooKeeper response and rejects any declared length that is negative or exceeds zooKeeperMaxFrameSize. This guards against decoding an absurdly large buffer (unbounded allocation) when the peer is misbehaving, the stream is misaligned, or the connection is talking to something that is not a ZooKeeper server.
Source
Thrown at agents/drivers/argo-go/zookeeper_protocol.go:363
header := make([]byte, 4)
binary.BigEndian.PutUint32(header, uint32(len(payload)))
if err := writeAll(client.connection, header); err != nil {
return err
}
return writeAll(client.connection, payload)
}
func (client *protocolZooKeeperClient) readFrame() ([]byte, error) {
if err := client.connection.SetReadDeadline(time.Now().Add(client.timeout)); err != nil {
return nil, err
}
header := make([]byte, 4)
if _, err := io.ReadFull(client.connection, header); err != nil {
return nil, err
}
length := int(binary.BigEndian.Uint32(header))
if length < 0 || length > zooKeeperMaxFrameSize {
return nil, fmt.Errorf("ZooKeeper response frame is %d bytes, maximum is %d", length, zooKeeperMaxFrameSize)
}
payload := make([]byte, length)
if _, err := io.ReadFull(client.connection, payload); err != nil {
return nil, err
}
return payload, nil
}
func writeAll(writer io.Writer, payload []byte) error {
for len(payload) > 0 {
written, err := writer.Write(payload)
if err != nil {
return err
}
if written <= 0 {
return io.ErrShortWrite
}
payload = payload[written:]View on GitHub (pinned to c0390bff16)
Solutions
- Verify the connection address actually points to a ZooKeeper quorum member (default port 2181) — connect to a wrong service and its response bytes are parsed as a length header.
- Close and re-dial the client; the stream is likely desynchronized after an earlier error or timeout, and framing cannot recover mid-connection.
- Check for TLS/plaintext mismatch: if the server requires TLS and you dial plain TCP (or vice versa), the handshake bytes produce garbage lengths.
- Confirm any intermediary (proxy, port-forward) is TCP-transparent and not injecting data into the stream.
- If you legitimately need responses bigger than the cap, raise zooKeeperMaxFrameSize along with the server's jute.maxbuffer.
Example fix
// before
client, _, err := zk.Connect([]string{"10.0.0.5:80"}, time.Second*5) // wrong service/port
// after
client, _, err := zk.Connect([]string{"zk-1.internal:2181,zk-2.internal:2181"}, time.Second*5)
if err != nil {
return err
}
client = client // re-dial on framing errors; do not reuse a connection after this error Defensive patterns
Strategy: retry
Validate before calling
// validate the endpoint before dialing
host, port, err := net.SplitHostPort(connStr)
if err != nil || port != "2181" {
return fmt.Errorf("suspicious ZooKeeper endpoint %q", connStr)
}
conn, err := net.DialTimeout("tcp", connStr, 3*time.Second)
if err != nil {
return err
}
conn.Close() Try / catch
resp, err := client.request(payload)
if err != nil && strings.Contains(err.Error(), "response frame is") {
client.Close()
client = redial() // framing is unrecoverable on this socket
resp, err = client.request(payload) // bounded retry, once
}
if err != nil {
return err
} Prevention
- Double-check the ZooKeeper connection string (host:2181) — wrong ports/services are the top cause.
- Never reuse a client connection after a framing/timeout error; always re-dial.
- Ensure TLS settings match the server; a plaintext dial to a TLS port yields garbage lengths.
- Keep intermediaries (proxies, port-forwards) TCP-transparent and free of injected data.
When it happens
Trigger: Calling any request (Get/Children/Exists, etc.) when the response stream is desynchronized; connecting to a non-ZooKeeper service on the configured address; reading a partially-written or corrupted response; a length header whose bytes were shifted by a prior failed frame read.
Common situations: Wrong host/port in the ZooKeeper connection string (pointing at an HTTP server or another service that answers with bytes parsed as a giant length); a proxy/load balancer injecting HTML or TLS bytes; stale connection reused after a previous mid-frame timeout corrupted the framing.
Related errors
- ZooKeeper request frame is %d bytes, maximum is %d
- invalid ZooKeeper buffer length %d
- ZooKeeper sent an unexpected token after GSSAPI completion
- ZooKeeper connection is nil
- ZooKeeper sent an unexpected token after GSSAPI completion
AI-assisted analysis of t8y2/dbx@c0390bff16 (2026-09-05).
Data as JSON: /api/errors/f5806a98963a8f40.
Report an issue: GitHub.