dgraph-io/dgraph · error

Duplicate key in similar_to options: %q

Error message

Duplicate key in similar_to options: %q

What it means

This error is thrown while parsing the 'similar_to' query option string in worker/task.go. The option string is a comma/semicolon separated list of key:value pairs; before applying a pair the parser records each key in a 'seen' set and rejects any key that appears more than once. It protects against ambiguous or accidental repeated configuration of the same vector-search option.

Source

Thrown at worker/task.go:2792

func parseSimilarToOptions(args []string, fc *functionContext) error {
	if len(args) == 0 {
		return nil
	}
	if len(args)%2 != 0 {
		return errors.Errorf("Malformed option in similar_to: expected key:value pairs, got %v", args)
	}
	seen := make(map[string]struct{}, len(args)/2)
	for i := 0; i < len(args); i += 2 {
		k := strings.ToLower(strings.TrimSpace(args[i]))
		v := strings.TrimSpace(args[i+1])
		if strings.HasSuffix(k, ":") {
			k = strings.TrimSuffix(k, ":")
		}
		if len(k) == 0 {
			return errors.Errorf("Malformed option in similar_to: empty key")
		}
		if _, dup := seen[k]; dup {
			return errors.Errorf("Duplicate key in similar_to options: %q", k)
		}
		seen[k] = struct{}{}

		v = strings.Trim(v, "\"'")
		switch k {
		case "ef":
			n, perr := strconv.ParseInt(v, 10, 32)
			if perr != nil {
				return errors.Errorf("Invalid value for 'ef' in similar_to: %q", v)
			}
			if n <= 0 {
				return errors.Errorf("Value for 'ef' must be positive, got: %d", n)
			}
			fc.vsEfOverride = int(n)
		case "distance_threshold":
			f, perr := strconv.ParseFloat(v, 64)
			if perr != nil {
				return errors.Errorf("Invalid value for 'distance_threshold' in similar_to: %q", v)

View on GitHub (pinned to 759e242be6)

Solutions

  1. Inspect the similar_to option string in the failing query and remove the duplicated key, keeping a single 'ef' / 'distance_threshold' entry.
  2. If you need to change the value, replace the earlier occurrence instead of appending a second pair.
  3. If the option string is built by code, de-duplicate keys (e.g. a map) before serializing.

Example fix

// before
query += "; ef: 100; ef: 200"
// after
query += "; ef: 200"
Defensive patterns

Strategy: validation

Validate before calling

keys := strings.Split(optString, ";")
seen := map[string]bool{}
for _, kv := range keys {
    parts := strings.SplitN(kv, ":", 2)
    if len(parts) != 2 { continue }
    k := strings.TrimSuffix(strings.TrimSpace(parts[0]), ":")
    if seen[k] { return fmt.Errorf("duplicate similar_to key: %s", k) }
    seen[k] = true
}

Try / catch

var parseErr *ErrSimilarToOptions
if err := runQuery(ctx); err != nil && errors.As(err, &parseErr) {
    // surface the offending duplicate key to the caller
    return fmt.Errorf("fix similar_to options: %w", err)
}

Prevention

When it happens

Trigger: A DQL query contains a similar_to option string with the same key twice, e.g. 'similar_to: "vec; ef: 100; ef: 50"' or an option ending in a duplicated colon such as 'ef:: 10; ef: 20' after trimming. Any caller constructing the option string programmatically that appends 'ef' twice will hit it.

Common situations: Hand-written DQL where an option line was copy-pasted and a duplicate 'ef' or 'distance_threshold' pair left in; template-driven query builders concatenating option fragments that both set 'ef'; case where the same key is spelled identically after the parser lowercases/trims trailing colons.

Related errors


AI-assisted analysis of dgraph-io/dgraph@759e242be6 (2026-09-01). Data as JSON: /api/errors/5aec8160944dca69. Report an issue: GitHub.