go-redis/redis · error

invalid total results format

Error message

invalid total results format

What it means

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.

Source

Thrown at search_commands.go:2613

			if result.Suggestions != nil {
				val[i].Suggestions = slices.Clone(result.Suggestions)
			}
		}
	}
	return &FTSpellCheckCmd{
		baseCmd: cmd.cloneBaseCmd(),
		val:     val,
	}
}

func parseFTSearch(data []interface{}, noContent, withScores, withPayloads, withSortKeys bool) (FTSearchResult, error) {
	if len(data) < 1 {
		return FTSearchResult{}, fmt.Errorf("unexpected search result format")
	}

	total, ok := data[0].(int64)
	if !ok {
		return FTSearchResult{}, fmt.Errorf("invalid total results format")
	}

	var results []Document
	for i := 1; i < len(data); {
		docID, ok := data[i].(string)
		if !ok {
			return FTSearchResult{}, fmt.Errorf("invalid document ID format")
		}

		doc := Document{
			ID:     docID,
			Fields: make(map[string]string),
		}
		i++

		if noContent {
			results = append(results, doc)
			continue

View on GitHub (pinned to 36d97525cd)

Solutions

  1. Verify the index exists and was created with FT.CREATE before searching.
  2. Check the server is Redis Stack (RediSearch) and not vanilla Redis, which has no FT.SEARCH.
  3. Inspect cmd.RawResult() to see the actual reply shape and compare against the FT.SEARCH contract.
  4. If a proxy is in play, bypass it and call Redis directly to confirm the raw reply.

Example fix

// before
res, err := client.FTSearchWithArgs(ctx, "idx", "*", opts).Result()
// after — inspect the raw reply first when the error is unexpected
raw, err := client.FTSearchWithArgs(ctx, "idx", "*", opts).RawResult()
if err != nil { log.Printf("raw reply: %#v", raw) }
Defensive patterns

Strategy: try-catch

Try / catch

res, err := client.FTSearchWithArgs(ctx, idx, q, opts).Result()
if err != nil {
    if strings.Contains(err.Error(), "invalid total results format") {
        raw, _ := cmd.RawResult()
        log.Printf("ft.search total_results not int64; raw=%#v", raw)
    }
    return err
}

Prevention

When it happens

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

Common situations: 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.

Related errors


AI-assisted analysis of go-redis/redis@36d97525cd (2026-08-06). Data as JSON: /data/errors/1ce1c63f7d4d19ad.json. Report an issue: GitHub.