go-redis/redis · error

FT.CREATE: SCHEMA VectorArgs must have exactly one of FlatOp

Error message

FT.CREATE: SCHEMA VectorArgs must have exactly one of FlatOptions, HNSWOptions, or VamanaOptions

What it means

Returned by FTCreate when FTVectorArgs does not have exactly one of FlatOptions, HNSWOptions, or VamanaOptions set. RediSearch requires a single vector algorithm choice; setting zero (no algorithm) or more than one (ambiguous) is rejected client-side at search_commands.go:1480.

Source

Thrown at search_commands.go:1482

			if schema.FieldType != SearchFieldTypeVector {
				cmd := NewStatusCmd(ctx, args...)
				cmd.SetErr(fmt.Errorf("FT.CREATE: SCHEMA FieldType VECTOR is required for VectorArgs"))
				return cmd
			}
			// Check mutual exclusivity of vector options
			optionCount := 0
			if schema.VectorArgs.FlatOptions != nil {
				optionCount++
			}
			if schema.VectorArgs.HNSWOptions != nil {
				optionCount++
			}
			if schema.VectorArgs.VamanaOptions != nil {
				optionCount++
			}
			if optionCount != 1 {
				cmd := NewStatusCmd(ctx, args...)
				cmd.SetErr(fmt.Errorf("FT.CREATE: SCHEMA VectorArgs must have exactly one of FlatOptions, HNSWOptions, or VamanaOptions"))
				return cmd
			}
			if schema.VectorArgs.FlatOptions != nil {
				args = append(args, "FLAT")
				if schema.VectorArgs.FlatOptions.Type == "" || schema.VectorArgs.FlatOptions.Dim == 0 || schema.VectorArgs.FlatOptions.DistanceMetric == "" {
					cmd := NewStatusCmd(ctx, args...)
					cmd.SetErr(fmt.Errorf("FT.CREATE: Type, Dim and DistanceMetric are required for VECTOR FLAT"))
					return cmd
				}
				flatArgs := []interface{}{
					"TYPE", schema.VectorArgs.FlatOptions.Type,
					"DIM", schema.VectorArgs.FlatOptions.Dim,
					"DISTANCE_METRIC", schema.VectorArgs.FlatOptions.DistanceMetric,
				}
				if schema.VectorArgs.FlatOptions.InitialCapacity > 0 {
					flatArgs = append(flatArgs, "INITIAL_CAP", schema.VectorArgs.FlatOptions.InitialCapacity)
				}
				if schema.VectorArgs.FlatOptions.BlockSize > 0 {

View on GitHub (pinned to 36d97525cd)

Solutions

  1. Set exactly one of FlatOptions, HNSWOptions, or VamanaOptions on FTVectorArgs.
  2. Reset the unused algorithm pointers to nil when switching algorithms at runtime.
  3. Use a builder/switch that assigns one option struct and leaves the others nil.

Example fix

// before (two set)
&redis.FTVectorArgs{FlatOptions: f, HNSWOptions: h}

// after (exactly one)
&redis.FTVectorArgs{HNSWOptions: h}
Defensive patterns

Strategy: validation

Validate before calling

func countVecOpts(v *redis.FTVectorArgs) int {
    n := 0
    if v.FlatOptions != nil { n++ }
    if v.HNSWOptions != nil { n++ }
    if v.VamanaOptions != nil { n++ }
    return n
}
if n := countVecOpts(f.VectorArgs); n != 1 {
    return fmt.Errorf("exactly one vector algorithm required, got %d", n)
}

Prevention

When it happens

Trigger: Constructing FTVectorArgs{} with no options set, or populating two option structs (e.g. FlatOptions and HNSWOptions) simultaneously. The optionCount counter at line 1470 must equal exactly 1.

Common situations: Conditionally building options where a switch falls through leaving none set, or merging configs that accidentally set multiple algorithm options. Also happens when migrating between algorithms and forgetting to nil the old field.

Related errors


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