redis/go-redis · error
invalid total_results format
Error message
invalid total_results format
What it means
The FT.HYBRID reply parser expects a numeric field "total_results" in the reply map. If that key is missing or its value is not an int64, the client returns this error. It signals the server reply does not follow the expected FT.HYBRID result structure.
Source
Thrown at search_commands.go:3066
}
// Handle cursor result
if withCursor {
searchCursorID, ok1 := resultMap["SEARCH"].(int64)
vsimCursorID, ok2 := resultMap["VSIM"].(int64)
if !ok1 || !ok2 {
return FTHybridResult{}, nil, fmt.Errorf("invalid cursor result format")
}
return FTHybridResult{}, &FTHybridCursorResult{
SearchCursorID: int(searchCursorID),
VsimCursorID: int(vsimCursorID),
}, nil
}
// Parse regular result
totalResults, ok := resultMap["total_results"].(int64)
if !ok {
return FTHybridResult{}, nil, fmt.Errorf("invalid total_results format")
}
resultsData, ok := resultMap["results"].([]interface{})
if !ok {
return FTHybridResult{}, nil, fmt.Errorf("invalid results format")
}
// Parse each result item
results := make([]map[string]interface{}, 0, len(resultsData))
for _, item := range resultsData {
// Try parsing as map[string]interface{} first (RESP3 format)
if itemMap, ok := item.(map[string]interface{}); ok {
results = append(results, itemMap)
continue
}
// Try parsing as map[interface{}]interface{} (alternative RESP3 format)
if rawMap, ok := item.(map[interface{}]interface{}); ok {View on GitHub (pinned to c5cad058c7)
Solutions
- Align go-redis and server versions so the FT.HYBRID reply contract matches
- Use Protocol: 3 to get the RESP3 map reply path the parser expects
- Inspect the raw reply (ProcessHook or MONITOR) to confirm whether "total_results" exists and its type
- Fix mocks to include "total_results" as int64
Example fix
// before
map[interface{}]interface{}{"results": []interface{}{}}
// after
map[interface{}]interface{}{"total_results": int64(0), "results": []interface{}{}} Defensive patterns
Strategy: validation
Validate before calling
// pre-flight: ensure the endpoint responds to a basic FT.HYBRID call before relying on it _, err := rdb.Do(ctx, "FT.HYBRID", "idx", "QUERY", "*", "VSIM", "vec", "->", "1").Result()
Type guard
func hasTotalResults(m map[interface{}]interface{}) bool {
_, ok := m["total_results"].(int64)
return ok
} Try / catch
res, _, err := hybridCmd.Result()
if err != nil && strings.Contains(err.Error(), "invalid total_results format") {
// capture raw reply with a ProcessHook for bug report; treat as server incompatibility
return ErrReplyShapeUnsupported
} Prevention
- Keep go-redis and Redis Stack versions in the tested compatibility matrix
- Add integration tests for FT.HYBRID result parsing
- Avoid middleware that renames or re-types reply fields
When it happens
Trigger: Calling FTHybrid against a server whose reply omits "total_results" or returns it with a different type/name (different RediSearch build, proxy rewrite, or RESP protocol mismatch).
Common situations: Version skew between go-redis and the Redis stack server; a compatibility layer or RESP proxy renaming/re-typing fields; tests with hand-built maps lacking the key.
Related errors
- invalid key type at index %d
- invalid results format
- invalid result item format
- invalid item key format
- invalid cursor result format
AI-assisted analysis of redis/go-redis@c5cad058c7 (2026-09-01).
Data as JSON: /api/errors/fe3765d86113f167.
Report an issue: GitHub.