{"record":{"id":"df94561a2b7b2a18","repo":"redis/go-redis","slug":"redis-unexpected-key-q-in-cluster-links-reply","errorCode":null,"errorMessage":"redis: unexpected key %q in CLUSTER LINKS reply","messagePattern":"redis: unexpected key %q in CLUSTER LINKS reply","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"command.go","lineNumber":7521,"sourceCode":"\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\n\t\t\tswitch key {\n\t\t\tcase \"direction\":\n\t\t\t\tcmd.val[i].Direction, err = rd.ReadString()\n\t\t\tcase \"node\":\n\t\t\t\tcmd.val[i].Node, err = rd.ReadString()\n\t\t\tcase \"create-time\":\n\t\t\t\tcmd.val[i].CreateTime, err = rd.ReadInt()\n\t\t\tcase \"events\":\n\t\t\t\tcmd.val[i].Events, err = rd.ReadString()\n\t\t\tcase \"send-buffer-allocated\":\n\t\t\t\tcmd.val[i].SendBufferAllocated, err = rd.ReadInt()\n\t\t\tcase \"send-buffer-used\":\n\t\t\t\tcmd.val[i].SendBufferUsed, err = rd.ReadInt()\n\t\t\tdefault:\n\t\t\t\treturn fmt.Errorf(\"redis: unexpected key %q in CLUSTER LINKS reply\", key)\n\t\t\t}\n\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\t}\n\n\treturn nil\n}\n\nfunc (cmd *ClusterLinksCmd) Clone() Cmder {\n\tvar val []ClusterLink\n\tif cmd.val != nil {\n\t\tval = make([]ClusterLink, len(cmd.val))\n\t\tcopy(val, cmd.val)\n\t}\n\treturn &ClusterLinksCmd{","sourceCodeStart":7503,"sourceCodeEnd":7539,"githubUrl":"https://github.com/redis/go-redis/blob/c5cad058c72f58370553b48566302303cf8a2e89/command.go#L7503-L7539","documentation":"This error is raised when parsing the CLUSTER LINKS reply and the reply map contains a key the parser does not recognize. CLUSTER LINKS returns per-peer link attributes; go-redis maps a fixed set of them (direction, node names, events, buffers, etc.) onto the ClusterLink struct and errors on unknown keys so data is not silently lost.","triggerScenarios":"Calling ClusterLinks() against a Redis version that adds a new attribute to CLUSTER LINKS output that this client version's switch statement (command.go:~7521) does not cover.","commonSituations":"Newer Redis server (7.x+ feature, evolving fields) with an older go-redis; running CLUSTER LINKS through an admin tool or proxy that appends fields.","solutions":["Upgrade go-redis to the latest version so new CLUSTER LINKS fields are recognized.","Compare the raw CLUSTER LINKS output (redis-cli CLUSTER LINKS) to the fields your client supports.","If a genuinely new field is unsupported, open an issue on redis/go-redis to add it.","Temporarily avoid ClusterLinks() and use redis-cli for link inspection."],"exampleFix":"// before: new server field 'peer-epoch' trips the parser\nlinks, err := rdb.ClusterLinks(ctx)\n// redis: unexpected key \"peer-epoch\" in CLUSTER LINKS reply\n\n// after: upgrade go-redis\n// go get github.com/redis/go-redis/v9@latest\nlinks, err := rdb.ClusterLinks(ctx)","handlingStrategy":"try-catch","validationCode":"// inspect raw CLUSTER LINKS output\nraw, err := rdb.Do(ctx, \"CLUSTER\", \"LINKS\").Result()\n_ = raw // compare keys to what your client supports","typeGuard":null,"tryCatchPattern":"links, err := rdb.ClusterLinks(ctx)\nif err != nil {\n    if strings.Contains(err.Error(), \"CLUSTER LINKS reply\") {\n        // fall back to rdb.Do(ctx, \"CLUSTER\", \"LINKS\") and parse manually\n    }\n    return err\n}","preventionTips":["Upgrade go-redis when adopting newer Redis cluster versions","Diff CLUSTER LINKS output against supported fields after server upgrades","Use redis-cli to sanity-check cluster admin command output","Keep cluster admin tooling on a supported client version"],"tags":["redis","cluster","reply-parsing","cluster-links"],"backgroundTag":"unsupported-server-reply-format","analyzedSha":"c5cad058c72f58370553b48566302303cf8a2e89","analyzedAt":"2026-09-01T06:50:53.388Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}