{"record":{"id":"076afed6247e6910","repo":"t8y2/dbx","slug":"decode-zookeeper-session-password-w","errorCode":null,"errorMessage":"decode ZooKeeper session password: %w","messagePattern":"decode ZooKeeper session password: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"agents/drivers/argo-go/zookeeper_protocol.go","lineNumber":174,"sourceCode":"\t\treturn nil, fmt.Errorf(\"send ZooKeeper connect request: %w\", err)\n\t}\n\tresponse, err := client.readFrame()\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"read ZooKeeper connect response: %w\", err)\n\t}\n\tdecoder := newZooKeeperDecoder(response)\n\tif _, err := decoder.int32(); err != nil {\n\t\treturn nil, fmt.Errorf(\"decode ZooKeeper protocol version: %w\", err)\n\t}\n\tif _, err := decoder.int32(); err != nil {\n\t\treturn nil, fmt.Errorf(\"decode ZooKeeper session timeout: %w\", err)\n\t}\n\tsessionID, err := decoder.int64()\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"decode ZooKeeper session ID: %w\", err)\n\t}\n\tif _, err := decoder.bytes(); err != nil {\n\t\treturn nil, fmt.Errorf(\"decode ZooKeeper session password: %w\", err)\n\t}\n\tif sessionID == 0 {\n\t\treturn nil, zk.ErrSessionExpired\n\t}\n\treturn client, nil\n}\n\nfunc zooKeeperTimeoutMillis(timeout time.Duration) int32 {\n\tmilliseconds := timeout.Milliseconds()\n\tif milliseconds < 1 {\n\t\treturn 1\n\t}\n\tif milliseconds > math.MaxInt32 {\n\t\treturn math.MaxInt32\n\t}\n\treturn int32(milliseconds)\n}\n","sourceCodeStart":156,"sourceCodeEnd":192,"githubUrl":"https://github.com/t8y2/dbx/blob/c0390bff16418b651f4728520d99adf8ce48829a/agents/drivers/argo-go/zookeeper_protocol.go#L156-L192","documentation":"The final field of the ZooKeeper connect response is the session password as a length-prefixed byte slice; if decoder.bytes() cannot read it, this wrapped error is returned. It is the last decode step of the handshake, so a failure here means the frame was almost complete but truncated or malformed at the tail.","triggerScenarios":"newProtocolZooKeeperClient decoding a response where the password length prefix or its bytes run past the end of the frame — truncated tail, wrong length prefix, or a fake response built without the password field.","commonSituations":"Manually crafted test responses missing the password bytes; frame off-by-one in a custom proxy; server implementations or versions emitting a different trailing layout.","solutions":["Verify the password field is present with a correct 4-byte length prefix followed by exactly that many bytes","Fix the test fake/handler to append the password bytes after the session ID","Inspect intermediaries for frame truncation and compare against a direct connection capture","Confirm ZooKeeper client/server wire-format compatibility"],"exampleFix":"// before (fake server)\nresp := append(version, timeout...)\nresp = append(resp, sessionID...) // password omitted\n// after\nresp = append(resp, sessionID...)\nresp = append(resp, int32(len(passwd)))\nresp = append(resp, passwd...)","handlingStrategy":"type-guard","validationCode":"func frameHasPassword(decoder *zooKeeperDecoder) bool {\n    return decoder.remaining() >= 4 // at least the password length prefix remains\n}","typeGuard":null,"tryCatchPattern":"client, err := newProtocolZooKeeperClient(conn, timeout)\nif err != nil {\n    if strings.Contains(err.Error(), \"decode ZooKeeper session password\") {\n        log.Error(\"connect response truncated at password field; fix frame length or length prefix\")\n    }\n    return err\n}","preventionTips":["Always append the length-prefixed password when constructing fake responses","Validate total frame length against the ConnectResponse layout before sending in tests","Diff fake responses byte-for-byte against real server captures"],"tags":["zookeeper","protocol","decoding"],"backgroundTag":"protocol-decode-failed","analyzedSha":"c0390bff16418b651f4728520d99adf8ce48829a","analyzedAt":"2026-09-05T23:05:10.900Z","contentChangedAt":"2026-09-05T23:05:10.900Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}