redis/go-redis · error

FT.HYBRID: vector Value must contain a blob at index 1

Error message

FT.HYBRID: vector Value must contain a blob at index 1

What it means

For a custom Vector implementation in FT.HYBRID, the client calls Value() and expects [paramName, blob] with the raw binary vector data at index 1. If the returned slice has fewer than 2 elements, there is no blob to send and this error is returned.

Source

Thrown at search_commands.go:3804

	switch vector := v.(type) {
	case *VectorFP32:
		return hybridVectorBytes(vector.Val)
	case *VectorFloat16:
		return hybridVectorBytes(vector.Val)
	case *VectorBFloat16:
		return hybridVectorBytes(vector.Val)
	case *VectorFloat64:
		return hybridVectorBytes(vector.Val)
	case *VectorInt8:
		return hybridVectorBytes(vector.Val)
	case *VectorUint8:
		return hybridVectorBytes(vector.Val)
	case *VectorValues, *VectorRef:
		return nil, fmt.Errorf("FT.HYBRID: unsupported vector type %T", v)
	default:
		values := v.Value()
		if len(values) < 2 {
			return nil, fmt.Errorf("FT.HYBRID: vector Value must contain a blob at index 1")
		}
		return values[1], nil
	}
}

func hybridVectorBytes(blob []byte) ([]byte, error) {
	if len(blob) == 0 {
		return nil, fmt.Errorf("FT.HYBRID: vector blob is required")
	}
	return blob, nil
}

// generateVectorParamName returns a parameter name that is not already present
// in params. It is used to pass vector data via the PARAMS mechanism when the
// caller does not provide a VectorParamName, since inline vector blobs are no
// longer supported by Redis.
func generateVectorParamName(params map[string]interface{}) string {
	for i := 0; ; i++ {

View on GitHub (pinned to c5cad058c7)

Solutions

  1. Return at least two elements from Value(), with the encoded binary vector as element 1.
  2. Reuse a built-in blob type like *VectorFP32 to avoid implementing Value() yourself.
  3. Encode floats to little-endian bytes (or use VectorFP32's encoding) before returning them.

Example fix

// before
func (v *myVec) Value() []interface{} { return []interface{}{"vec_param"} }
// after
func (v *myVec) Value() []interface{} { return []interface{}{"vec_param", float32LEBytes(v.data)} }
Defensive patterns

Strategy: validation

Validate before calling

vals := myVec.Value()
if len(vals) < 2 {
    return errors.New("custom Vector.Value() must return [name, blob]")
}

Type guard

func customVectorOK(v redis.Vector) bool {
    return len(v.Value()) >= 2
}

Try / catch

cmd := client.FTHybridWithArgs(ctx, "idx", opts)
if err := cmd.Err(); err != nil && strings.Contains(err.Error(), "blob at index 1") {
    // fix Value() implementation before retrying
}

Prevention

When it happens

Trigger: Passing a custom Vector type to FTHybridWithArgs whose Value() returns a slice of length 0 or 1 (e.g. only the parameter name, or an empty slice).

Common situations: Custom Vector implementations written for another command's contract returning just the float values; forgetting that FT.HYBRID needs name-then-blob ordering.

Related errors


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