{"id":"1ce1c63f7d4d19ad","repo":"go-redis/redis","slug":"invalid-total-results-format","errorCode":null,"errorMessage":"invalid total results format","messagePattern":"invalid total results format","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"search_commands.go","lineNumber":2613,"sourceCode":"\t\t\tif result.Suggestions != nil {\n\t\t\t\tval[i].Suggestions = slices.Clone(result.Suggestions)\n\t\t\t}\n\t\t}\n\t}\n\treturn &FTSpellCheckCmd{\n\t\tbaseCmd: cmd.cloneBaseCmd(),\n\t\tval:     val,\n\t}\n}\n\nfunc parseFTSearch(data []interface{}, noContent, withScores, withPayloads, withSortKeys bool) (FTSearchResult, error) {\n\tif len(data) < 1 {\n\t\treturn FTSearchResult{}, fmt.Errorf(\"unexpected search result format\")\n\t}\n\n\ttotal, ok := data[0].(int64)\n\tif !ok {\n\t\treturn FTSearchResult{}, fmt.Errorf(\"invalid total results format\")\n\t}\n\n\tvar results []Document\n\tfor i := 1; i < len(data); {\n\t\tdocID, ok := data[i].(string)\n\t\tif !ok {\n\t\t\treturn FTSearchResult{}, fmt.Errorf(\"invalid document ID format\")\n\t\t}\n\n\t\tdoc := Document{\n\t\t\tID:     docID,\n\t\t\tFields: make(map[string]string),\n\t\t}\n\t\ti++\n\n\t\tif noContent {\n\t\t\tresults = append(results, doc)\n\t\t\tcontinue","sourceCodeStart":2595,"sourceCodeEnd":2631,"githubUrl":"https://github.com/go-redis/redis/blob/36d97525cd8076aed67cddf54778e9ea84550929/search_commands.go#L2595-L2631","documentation":"Returned by FTSearchCmd.readReply while parsing a RESP2 FT.SEARCH reply: the first element of the result array must be the total-results count as an int64. go-redis asserts data[0] is int64 (search_commands.go:2611-2613); anything else (e.g. a bulk string, nil, or a nested array) means the server reply shape does not match the FT.SEARCH contract.","triggerScenarios":"Calling FTSearch/FTSearchWithArgs against a server whose reply is not a standard FT.SEARCH array — e.g. querying an index that does not exist via a path that returns an error blob, hitting a proxy that re-shapes replies, or running against a Redis Stack version whose FT.SEARCH returns COUNT as a string.","commonSituations":"Wrong index name returned a non-array reply, RESP2 forced (Protocol:2) against a server emitting RESP3-only shapes, or a man-in-the-middle/proxy (twemproxy, RESP proxy) mangling the response.","solutions":["Verify the index exists and was created with FT.CREATE before searching.","Check the server is Redis Stack (RediSearch) and not vanilla Redis, which has no FT.SEARCH.","Inspect cmd.RawResult() to see the actual reply shape and compare against the FT.SEARCH contract.","If a proxy is in play, bypass it and call Redis directly to confirm the raw reply."],"exampleFix":"// before\nres, err := client.FTSearchWithArgs(ctx, \"idx\", \"*\", opts).Result()\n// after — inspect the raw reply first when the error is unexpected\nraw, err := client.FTSearchWithArgs(ctx, \"idx\", \"*\", opts).RawResult()\nif err != nil { log.Printf(\"raw reply: %#v\", raw) }","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"res, err := client.FTSearchWithArgs(ctx, idx, q, opts).Result()\nif err != nil {\n    if strings.Contains(err.Error(), \"invalid total results format\") {\n        raw, _ := cmd.RawResult()\n        log.Printf(\"ft.search total_results not int64; raw=%#v\", raw)\n    }\n    return err\n}","preventionTips":["Always create the index with FT.CREATE before searching.","Confirm the server is Redis Stack, not vanilla Redis.","Keep go-redis and Redis Stack on matched current versions."],"tags":["redisearch","ft-search","resp2","response-parsing"],"analyzedSha":"36d97525cd8076aed67cddf54778e9ea84550929","analyzedAt":"2026-08-06T01:08:27.376Z","schemaVersion":2}