t8y2/dbx · error

invalid ZooKeeper string vector length %d

Error message

invalid ZooKeeper string vector length %d

What it means

When decoding a string vector (e.g. the children list returned by a getChildren reply), the vector's element count must be either -1 (NULL) or a bounded positive number (at most zooKeeperMaxFrameSize/4). Any other value — negative or implausibly large — indicates a corrupt or misaligned stream, so decoder.strings refuses to preallocate and iterate over it.

Source

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

	}
	return append([]byte(nil), value...), nil
}

func (decoder *zooKeeperDecoder) string() (string, error) {
	value, err := decoder.bytes()
	return string(value), err
}

func (decoder *zooKeeperDecoder) strings() ([]string, error) {
	length, err := decoder.int32()
	if err != nil {
		return nil, err
	}
	if length == -1 {
		return nil, nil
	}
	if length < -1 || length > zooKeeperMaxFrameSize/4 {
		return nil, fmt.Errorf("invalid ZooKeeper string vector length %d", length)
	}
	values := make([]string, 0, length)
	for index := int32(0); index < length; index++ {
		value, valueErr := decoder.string()
		if valueErr != nil {
			return nil, valueErr
		}
		values = append(values, value)
	}
	return values, nil
}

func (decoder *zooKeeperDecoder) stat() (*zk.Stat, error) {
	stat := &zk.Stat{}
	var err error
	if stat.Czxid, err = decoder.int64(); err != nil {
		return nil, err
	}

View on GitHub (pinned to c0390bff16)

Solutions

  1. Close and re-dial the client connection; the stream is misaligned and subsequent reads on the same socket will also fail.
  2. Verify the connection targets a genuine ZooKeeper server and that no TLS/proxy layer is transforming the bytes.
  3. Avoid sharing the client (and its underlying connection) across concurrent goroutines without synchronization; interleaved reads shift the framing.
  4. If the node legitimately has an enormous number of children, paginate by structuring children under nested parent znodes instead of one flat list.

Example fix

// before
children, _, err := zkClient.Children("/jobs") // connection shared unsafely

// after
client.mu.Lock()
children, _, err := zkClient.Children("/jobs")
client.mu.Unlock()
if err != nil {
    client.reconnect() // discard misaligned stream
    return err
}
Defensive patterns

Strategy: retry

Validate before calling

// sanity-check the node before listing children on a suspicious stream
exists, _, err := zkClient.Exists(path)
if err != nil || !exists {
    return fmt.Errorf("node %q unavailable: %v", path, err)
}

Type guard

func isInvalidVectorLength(err error) bool {
    return err != nil && strings.Contains(err.Error(), "invalid ZooKeeper string vector length")
}

Try / catch

children, _, err := zkClient.Children(path)
if isInvalidVectorLength(err) {
    zkClient.Close()
    zkClient = redial() // misaligned stream; re-dial and retry once
    children, _, err = zkClient.Children(path)
}
if err != nil {
    return err
}

Prevention

When it happens

Trigger: Calling Children (getChildren) when the reply's count field is garbage: reading a desynchronized stream after an earlier failed request, connecting to a non-ZooKeeper service, or frame bytes altered in transit so the count int32 reads as a huge or negative number.

Common situations: A directory node with a corrupted/oversized children list being read after a proxy mangled the response; sharing one client connection across goroutines so responses interleave; a port-forward or service mesh returning an error page parsed as a vector length.

Related errors


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