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 a 4-byte big-endian length prefix from the ZooKeeper connection, then reads exactly that many payload bytes. If the declared frame length is negative or exceeds zooKeeperMaxFrameSize, the client refuses to allocate that buffer and returns this error instead. This protects the client from corrupted responses and from malicious/broken servers that would otherwise trigger huge or impossible allocations.
Source
Thrown at agents/drivers/hive-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 actually points at a ZooKeeper server (correct host/port, no generic TCP proxy echoing garbage).
- Reduce the response size: narrow the query (smaller result sets, use Children instead of large getData payloads) so the reply fits under the frame cap.
- Check the network path (TLS termination, HAProxy) for stream corruption or truncation; enable TLS on both ends if required.
- If legitimately huge responses are expected, raise zooKeeperMaxFrameSize and redeploy, accepting the larger memory footprint.
- Re-establish the connection after the error; protocol state may be desynced and further reads will fail.
Example fix
// before
client, _ := hive.Dial("zk://10.0.0.1:9999") // wrong port: not ZooKeeper
children, err := client.Children("/a/very/large/znode")
// after
client, _ := hive.Dial("zk://10.0.0.1:2181") // correct ZooKeeper port
children, err := client.Children("/a/large/znode") // or fetch in smaller chunks Defensive patterns
Strategy: validation
Validate before calling
// before dialing, sanity-check the endpoint is a ZooKeeper server
conn, err := net.DialTimeout("tcp", "10.0.0.1:2181", 5*time.Second)
if err != nil { log.Fatal(err) }
conn.SetDeadline(time.Now().Add(3 * time.Second))
conn.Write([]byte("ruok"))
buf := make([]byte, 8)
n, _ := conn.Read(buf)
if string(buf[:n]) != "imok" { log.Fatal("endpoint is not ZooKeeper") }
conn.Close() Type guard
func isFrameTooLarge(err error) bool {
return err != nil && strings.Contains(err.Error(), "maximum is")
} Try / catch
children, err := client.Children(path)
if err != nil {
if isFrameTooLarge(err) {
// reconnect (stream is desynced) and fall back to a smaller query
client.Close()
client, err = hive.Dial(connStr)
if err == nil {
children, err = client.Children(shardPath(path))
}
}
return fmt.Errorf("zk children: %w", err)
} Prevention
- Always point the client at a real ZooKeeper port (2181) and verify with the 'ruok' health check before use.
- Keep znode payloads and directory listings small so replies stay far below the frame cap.
- Avoid generic TCP proxies on the ZooKeeper path; use ones that preserve the byte stream if unavoidable.
- Recreate the client connection after any decode error instead of retrying on the same socket.
- Alert on this error in production — it usually means stream corruption, not a transient failure.
When it happens
Trigger: Any call through request (i.e. any ZooKeeper operation via newProtocolZooKeeperClient) when the server (or an intermediary proxy) sends a frame whose 4-byte length header decodes to a value above zooKeeperMaxFrameSize or negative; also hit by readZooKeeperTestFrame when a test frame header is malformed.
Common situations: Responses larger than the library's cap (e.g. a huge getChildren or getData reply), connecting to a non-ZooKeeper service on the configured port so random bytes are interpreted as a length header, a proxy/load balancer truncating or mangling TCP streams, or protocol desync after a partial read on a reused connection.
Related errors
- ZooKeeper connection timed out before a session was establis
- ZooKeeper session expired during connection
- ZooKeeper connection timed out before a session was establis
- ZooKeeper session expired during connection
- Connection timed out
AI-assisted analysis of t8y2/dbx@c0390bff16 (2026-09-05).
Data as JSON: /api/errors/dd442c0351fd8d0c.
Report an issue: GitHub.