{"record":{"id":"d5200ac4a72e4df2","repo":"redis/go-redis","slug":"invalid-results-format","errorCode":null,"errorMessage":"invalid results format","messagePattern":"invalid results format","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"search_commands.go","lineNumber":3071,"sourceCode":"\t\tvsimCursorID, ok2 := resultMap[\"VSIM\"].(int64)\n\t\tif !ok1 || !ok2 {\n\t\t\treturn FTHybridResult{}, nil, fmt.Errorf(\"invalid cursor result format\")\n\t\t}\n\t\treturn FTHybridResult{}, &FTHybridCursorResult{\n\t\t\tSearchCursorID: int(searchCursorID),\n\t\t\tVsimCursorID:   int(vsimCursorID),\n\t\t}, nil\n\t}\n\n\t// Parse regular result\n\ttotalResults, ok := resultMap[\"total_results\"].(int64)\n\tif !ok {\n\t\treturn FTHybridResult{}, nil, fmt.Errorf(\"invalid total_results format\")\n\t}\n\n\tresultsData, ok := resultMap[\"results\"].([]interface{})\n\tif !ok {\n\t\treturn FTHybridResult{}, nil, fmt.Errorf(\"invalid results format\")\n\t}\n\n\t// Parse each result item\n\tresults := make([]map[string]interface{}, 0, len(resultsData))\n\tfor _, item := range resultsData {\n\t\t// Try parsing as map[string]interface{} first (RESP3 format)\n\t\tif itemMap, ok := item.(map[string]interface{}); ok {\n\t\t\tresults = append(results, itemMap)\n\t\t\tcontinue\n\t\t}\n\n\t\t// Try parsing as map[interface{}]interface{} (alternative RESP3 format)\n\t\tif rawMap, ok := item.(map[interface{}]interface{}); ok {\n\t\t\titemMap := make(map[string]interface{})\n\t\t\tfor k, v := range rawMap {\n\t\t\t\tif keyStr, ok := k.(string); ok {\n\t\t\t\t\titemMap[keyStr] = v\n\t\t\t\t}","sourceCodeStart":3053,"sourceCodeEnd":3089,"githubUrl":"https://github.com/redis/go-redis/blob/c5cad058c72f58370553b48566302303cf8a2e89/search_commands.go#L3053-L3089","documentation":"The FT.HYBRID parser expects the reply map's \"results\" field to be an []interface{} list of per-document items. If it is missing or of another type, this error is returned. It indicates the server reply structure does not match the expected hybrid search result format.","triggerScenarios":"Calling FTHybrid when the reply's \"results\" value is absent or not an array — e.g. server emitting a different container type, a proxy rewriting the reply, or RESP2/RESP3 shape mismatch.","commonSituations":"Version skew between client and RediSearch; middleware transforming arrays into other types; incorrect test fixtures.","solutions":["Align go-redis and Redis stack versions","Force Protocol: 3 so the expected RESP3 reply shape is used","Dump the raw reply with a hook to verify the \"results\" field type","Correct test fixtures to use []interface{} for \"results\""],"exampleFix":"// before\nmap[interface{}]interface{}{\"total_results\": int64(1), \"results\": \"none\"}\n// after\nmap[interface{}]interface{}{\"total_results\": int64(1), \"results\": []interface{}{}}","handlingStrategy":"validation","validationCode":"// smoke-test the hybrid path at startup\nerr := rdb.Do(ctx, \"FT.HYBRID\", \"idx\", \"QUERY\", \"*\", \"VSIM\", \"vec\", \"->\", \"1\").Err()","typeGuard":"func hasResultsArray(m map[interface{}]interface{}) bool {\n    _, ok := m[\"results\"].([]interface{})\n    return ok\n}","tryCatchPattern":"res, _, err := hybridCmd.Result()\nif err != nil && strings.Contains(err.Error(), \"invalid results format\") {\n    // log raw reply, disable hybrid search feature flag\n    featureFlags.Set(\"hybrid_search\", false)\n    return err\n}","preventionTips":["Test the full FT.HYBRID reply path in CI against the target server version","Use Protocol: 3 for hybrid search","Gate the hybrid feature behind a runtime capability check"],"tags":["redis","search","resp-protocol","deserialization"],"backgroundTag":"unexpected-response-shape","analyzedSha":"c5cad058c72f58370553b48566302303cf8a2e89","analyzedAt":"2026-09-01T06:50:53.388Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}