{"record":{"id":"f433ff4b3d3ef0c4","repo":"redis/go-redis","slug":"unexpected-search-result-format","errorCode":null,"errorMessage":"unexpected search result format","messagePattern":"unexpected search result format","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"search_commands.go","lineNumber":2608,"sourceCode":"\t\tval = make([]SpellCheckResult, len(cmd.val))\n\t\tfor i, result := range cmd.val {\n\t\t\tval[i] = SpellCheckResult{\n\t\t\t\tTerm: result.Term,\n\t\t\t}\n\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}","sourceCodeStart":2590,"sourceCodeEnd":2626,"githubUrl":"https://github.com/redis/go-redis/blob/c5cad058c72f58370553b48566302303cf8a2e89/search_commands.go#L2590-L2626","documentation":"parseFTSearch received an empty array for an FT.SEARCH reply (RESP2 path). A well-formed reply always has at least one element — the total-results integer — so zero elements means the response shape is not what this library expects.","triggerScenarios":"FTSearch with RESP2 (Protocol: 2) when the server/proxy returns an empty array instead of [total, id, fields, ...]; a fault-injecting proxy truncating replies; custom middleware returning an empty []interface{}.","commonSituations":"Proxy/middleware mangling FT.SEARCH responses; pointing at a non-RediSearch server; tests with truncated mock replies.","solutions":["Inspect the raw reply to confirm the server really sent an empty array","Remove/fix proxies or hooks that rewrite command replies","Confirm the target is RediSearch (FT.INFO) and versions are compatible","Check AddHook implementations aren't replacing cmd replies with empty slices"],"exampleFix":"// before: assuming reply is fine\nres, _ := rdb.FTSearch(ctx, \"idx\", \"query\").Result()\n\n// after: log raw reply on parse failure\nres, err := rdb.FTSearch(ctx, \"idx\", \"query\").Result()\nif err != nil {\n\tlog.Printf(\"ftsearch: %v\", err)\n}","handlingStrategy":"try-catch","validationCode":"// Verify the search index exists before querying\nif err := rdb.FTInfo(ctx, index).Err(); err != nil {\n\treturn fmt.Errorf(\"index missing: %w\", err)\n}","typeGuard":"func looksLikeFTSearchReply(v interface{}) bool {\n\tslice, ok := v.([]interface{})\n\treturn ok && len(slice) >= 1\n}","tryCatchPattern":"res, err := rdb.FTSearch(ctx, \"idx\", q).Result()\nif err != nil {\n\tif strings.Contains(err.Error(), \"unexpected search result format\") {\n\t\tlog.Printf(\"malformed FT.SEARCH reply (proxy/server issue): %v\", err)\n\t\treturn emptyResult, nil\n\t}\n\treturn err\n}","preventionTips":["Don't route FT.SEARCH through reply-rewriting proxies","Audit AddHook implementations for reply mutation","Confirm Protocol option suits your server/proxy combination"],"tags":["go-redis","ftsearch","resp-parsing"],"backgroundTag":"resp-reply-parse-failed","analyzedSha":"c5cad058c72f58370553b48566302303cf8a2e89","analyzedAt":"2026-09-01T06:50:53.388Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}