redis/go-redis · error
invalid cursor result format
Error message
invalid cursor result format
What it means
When FT.HYBRID is run WITHCURSOR, the reply map must contain integer cursor IDs under the keys "SEARCH" and "VSIM". If either key is missing or its value is not an int64, the client cannot construct the FTHybridCursorResult and returns this error. It means the cursor reply from the server did not match the expected two-cursor structure.
Source
Thrown at search_commands.go:3055
func parseFTHybrid(data []interface{}, withCursor bool) (FTHybridResult, *FTHybridCursorResult, error) {
// Convert to map
resultMap := make(map[string]interface{})
for i := 0; i < len(data); i += 2 {
if i+1 < len(data) {
key, ok := data[i].(string)
if !ok {
return FTHybridResult{}, nil, fmt.Errorf("invalid key type at index %d", i)
}
resultMap[key] = data[i+1]
}
}
// 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")
}
View on GitHub (pinned to c5cad058c7)
Solutions
- Upgrade go-redis (and/or the Redis stack server) so client and server agree on the FT.HYBRID cursor reply format
- Ensure Protocol: 3 is negotiated; cursor reply parsing may differ between RESP2 and RESP3
- Capture the raw reply via a hook/MONITOR and confirm the "SEARCH"/"VSIM" keys and their types
- Avoid proxies that rewrite reply values (e.g. converting int64 cursors to strings)
Defensive patterns
Strategy: fallback
Validate before calling
// only request cursor when the server build supports hybrid cursors
if !serverSupportsHybridCursor { opts.Cursor = false } Type guard
func hasHybridCursorReply(m map[interface{}]interface{}) bool {
_, ok1 := m["SEARCH"].(int64)
_, ok2 := m["VSIM"].(int64)
return ok1 && ok2
} Try / catch
res, cursor, err := hybridCmd.Result()
if err != nil {
if strings.Contains(err.Error(), "invalid cursor result format") {
// fall back to non-cursor query without CURSOR option
return runHybridWithoutCursor(ctx)
}
return err
} Prevention
- Verify server version supports FT.HYBRID WITHCURSOR with SEARCH/VSIM cursor keys
- Do not route search traffic through value-rewriting proxies
- Add an integration test covering the cursor path
When it happens
Trigger: Calling FTHybrid with the Cursor option against a server that does not return the expected {"SEARCH": int64, "VSIM": int64} cursor map — e.g. a RediSearch version with different cursor reply keys, or a proxy rewriting the reply.
Common situations: Server upgrade/downgrade changing FT.HYBRID cursor reply layout; hitting a non-Redis-compatible endpoint that lacks hybrid cursor support; RESP2/RESP3 protocol mismatch altering value types (e.g. cursor returned as string).
Related errors
- invalid key type at index %d
- invalid total_results format
- invalid results format
- invalid result item format
- invalid item key format
AI-assisted analysis of redis/go-redis@c5cad058c7 (2026-09-01).
Data as JSON: /api/errors/4d0e1c5deec4ccd5.
Report an issue: GitHub.