redis/go-redis · error

invalid results format

Error message

invalid results format

What it means

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.

Source

Thrown at search_commands.go:3071

		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 {
			itemMap := make(map[string]interface{})
			for k, v := range rawMap {
				if keyStr, ok := k.(string); ok {
					itemMap[keyStr] = v
				}

View on GitHub (pinned to c5cad058c7)

Solutions

  1. Align go-redis and Redis stack versions
  2. Force Protocol: 3 so the expected RESP3 reply shape is used
  3. Dump the raw reply with a hook to verify the "results" field type
  4. Correct test fixtures to use []interface{} for "results"

Example fix

// before
map[interface{}]interface{}{"total_results": int64(1), "results": "none"}
// after
map[interface{}]interface{}{"total_results": int64(1), "results": []interface{}{}}
Defensive patterns

Strategy: validation

Validate before calling

// smoke-test the hybrid path at startup
err := rdb.Do(ctx, "FT.HYBRID", "idx", "QUERY", "*", "VSIM", "vec", "->", "1").Err()

Type guard

func hasResultsArray(m map[interface{}]interface{}) bool {
    _, ok := m["results"].([]interface{})
    return ok
}

Try / catch

res, _, err := hybridCmd.Result()
if err != nil && strings.Contains(err.Error(), "invalid results format") {
    // log raw reply, disable hybrid search feature flag
    featureFlags.Set("hybrid_search", false)
    return err
}

Prevention

When it happens

Trigger: 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.

Common situations: Version skew between client and RediSearch; middleware transforming arrays into other types; incorrect test fixtures.

Related errors


AI-assisted analysis of redis/go-redis@c5cad058c7 (2026-09-01). Data as JSON: /api/errors/d5200ac4a72e4df2. Report an issue: GitHub.