{"id":"8cd2b90b96f3c992","repo":"go-redis/redis","slug":"unexpected-response-type-t","errorCode":null,"errorMessage":"unexpected response type: %T","messagePattern":"unexpected response type: %T","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"search_commands.go","lineNumber":1022,"sourceCode":"\t\tif mapVal, ok := cmd.rawVal.(map[interface{}]interface{}); ok {\n\t\t\tcmd.val, err = parseFTAggregateMapRESP3(mapVal)\n\t\t} else {\n\t\t\treturn fmt.Errorf(\"unexpected RESP3 response type: %T\", cmd.rawVal)\n\t\t}\n\t\treturn err\n\t}\n\n\t// RESP2 format or error response - use ReadReply to handle errors properly\n\tdata, err := rd.ReadReply()\n\tif err != nil {\n\t\treturn err\n\t}\n\tcmd.rawVal = data // Store raw value for debugging\n\tif dataSlice, ok := data.([]interface{}); ok {\n\t\tcmd.val, err = ProcessAggregateResult(dataSlice)\n\t\treturn err\n\t}\n\treturn fmt.Errorf(\"unexpected response type: %T\", data)\n}\n\n// parseFTAggregateMapRESP3 parses the RESP3 format response from FT.AGGREGATE.\n// It takes a map[interface{}]interface{} which is the raw response from ReadReply().\n// RESP3 format:\n//\n//\t%5\n//\t  $10 attributes => *0\n//\t  $13 total_results => :N\n//\t  $6 format => $6 STRING\n//\t  $7 results => *N (array of maps with extra_attributes, values)\n//\t  $7 warning => *N (array of strings)\nfunc parseFTAggregateMapRESP3(data map[interface{}]interface{}) (*FTAggregateResult, error) {\n\tresult := &FTAggregateResult{\n\t\tRows: make([]AggregateRow, 0),\n\t}\n\n\tfor k, v := range data {","sourceCodeStart":1004,"sourceCodeEnd":1040,"githubUrl":"https://github.com/go-redis/redis/blob/36d97525cd8076aed67cddf54778e9ea84550929/search_commands.go#L1004-L1040","documentation":"Returned by AggregateCmd.readReply in the non-RESP3 branch when the raw reply is not a []interface{}. FT.AGGREGATE RESP2 replies must be arrays; a bulk string, integer, nil, or map landing in this branch means the reply does not match either expected FT.AGGREGATE shape.","triggerScenarios":"AggregateCmd.readReply reads a reply that is neither RespMap nor an []interface{}. Triggered during response decoding when the top-level type is unexpected.","commonSituations":"Server returned a plain error string that ReadReply surfaced as a non-array (combined with a missed error path). RESP2/RESP3 negotiation mismatch. A reply from a different command parsed as AggregateCmd. Proxy rewriting the frame.","solutions":["Inspect cmd.RawVal() to see the actual decoded type and content.","Confirm the command sent was FT.AGGREGATE and that the server actually returned an aggregate reply.","Verify protocol negotiation (Options.Protocol) matches the server reply type.","Reproduce with redis-cli to localize whether the shape originates at the server or an intermediary."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"res, err := cmd.Result()\nif err != nil && strings.Contains(err.Error(), \"unexpected response type\") {\n    raw, _ := cmd.RawResult()\n    log.Printf(\"aggregate reply neither RESP3 map nor RESP2 array; raw=%v (%T)\", raw, raw)\n}\nreturn err","preventionTips":["Ensure the command sent was actually FT.AGGREGATE and parsed by AggregateCmd.","Verify protocol negotiation matches the server reply type.","Reproduce with redis-cli to localize the malformed shape."],"tags":["ft-aggregate","response-decoding","type-mismatch"],"analyzedSha":"36d97525cd8076aed67cddf54778e9ea84550929","analyzedAt":"2026-08-06T01:08:27.376Z","schemaVersion":2}