{"record":{"id":"00f9f0c8e1d29512","repo":"redis/go-redis","slug":"odd-length-key-value-array-of-length-d","errorCode":null,"errorMessage":"odd-length key/value array of length %d","messagePattern":"odd-length key/value array of length (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"search_collect.go","lineNumber":221,"sourceCode":"}\n\n// parseCollectEntry decodes a single collected entry from either the RESP3\n// map form or the RESP2 flat key/value array form into a CollectEntry. Keys\n// are passed through as-is: the server already returns them without the \"@\"\n// prefix.\nfunc parseCollectEntry(e interface{}) (CollectEntry, error) {\n\tswitch m := e.(type) {\n\tcase map[interface{}]interface{}: // RESP3\n\t\tout := make(CollectEntry, len(m))\n\t\tfor k, val := range m {\n\t\t\tout[fmt.Sprint(k)] = val\n\t\t}\n\t\treturn out, nil\n\tcase map[string]interface{}: // already string-keyed\n\t\treturn m, nil\n\tcase []interface{}: // RESP2 flat [field, value, field, value, ...]\n\t\tif len(m)%2 != 0 {\n\t\t\treturn nil, fmt.Errorf(\"odd-length key/value array of length %d\", len(m))\n\t\t}\n\t\tout := make(CollectEntry, len(m)/2)\n\t\tfor i := 0; i < len(m); i += 2 {\n\t\t\tkey, ok := m[i].(string)\n\t\t\tif !ok {\n\t\t\t\tkey = fmt.Sprint(m[i])\n\t\t\t}\n\t\t\tout[key] = m[i+1]\n\t\t}\n\t\treturn out, nil\n\tdefault:\n\t\treturn nil, fmt.Errorf(\"unexpected type %T, want map or key/value array\", e)\n\t}\n}\n","sourceCodeStart":203,"sourceCodeEnd":236,"githubUrl":"https://github.com/redis/go-redis/blob/c5cad058c72f58370553b48566302303cf8a2e89/search_collect.go#L203-L236","documentation":"Under RESP2 a COLLECT entry may arrive as a flat array [field, value, field, value, ...]. parseCollectEntry requires an even number of elements so each field pairs with a value; an odd-length array cannot be split into key/value pairs and fails with this error.","triggerScenarios":"parseCollectEntry receiving a []interface{} of odd length (e.g. a truncated or nil-valued final field) from a COLLECT reply; len(m)%2 != 0.","commonSituations":"RESP2 replies where a trailing value was dropped or a proxy mangled the entry; manually constructed test replies with a missing value.","solutions":["Use RESP3 (Protocol: 3) so entries arrive as maps and this flat-array path is avoided","Fix the proxy/truncation issue that dropped the trailing value","Check the wrapped index from \"redis: COLLECT entry %d\" to locate the malformed row"],"exampleFix":"// before\n[]interface{}{\"field1\", \"v1\", \"field2\"} // odd length\n// after\n[]interface{}{\"field1\", \"v1\", \"field2\", \"v2\"} // or switch to RESP3 maps","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"func isEvenKVArray(v interface{}) bool {\n    arr, ok := v.([]interface{})\n    return ok && len(arr)%2 == 0\n}","tryCatchPattern":null,"preventionTips":["Prefer RESP3 so entries decode as maps, skipping the flat-array path","Fix proxies/truncation that drop trailing values","Validate hand-built test replies are even-length"],"tags":["search","collect","resp2","reply-parsing"],"backgroundTag":"unexpected-reply-shape","analyzedSha":"c5cad058c72f58370553b48566302303cf8a2e89","analyzedAt":"2026-09-01T06:50:53.388Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}