{"record":{"id":"5aec8160944dca69","repo":"dgraph-io/dgraph","slug":"duplicate-key-in-similar-to-options-q","errorCode":null,"errorMessage":"Duplicate key in similar_to options: %q","messagePattern":"Duplicate key in similar_to options: %q","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"worker/task.go","lineNumber":2792,"sourceCode":"func parseSimilarToOptions(args []string, fc *functionContext) error {\n\tif len(args) == 0 {\n\t\treturn nil\n\t}\n\tif len(args)%2 != 0 {\n\t\treturn errors.Errorf(\"Malformed option in similar_to: expected key:value pairs, got %v\", args)\n\t}\n\tseen := make(map[string]struct{}, len(args)/2)\n\tfor i := 0; i < len(args); i += 2 {\n\t\tk := strings.ToLower(strings.TrimSpace(args[i]))\n\t\tv := strings.TrimSpace(args[i+1])\n\t\tif strings.HasSuffix(k, \":\") {\n\t\t\tk = strings.TrimSuffix(k, \":\")\n\t\t}\n\t\tif len(k) == 0 {\n\t\t\treturn errors.Errorf(\"Malformed option in similar_to: empty key\")\n\t\t}\n\t\tif _, dup := seen[k]; dup {\n\t\t\treturn errors.Errorf(\"Duplicate key in similar_to options: %q\", k)\n\t\t}\n\t\tseen[k] = struct{}{}\n\n\t\tv = strings.Trim(v, \"\\\"'\")\n\t\tswitch k {\n\t\tcase \"ef\":\n\t\t\tn, perr := strconv.ParseInt(v, 10, 32)\n\t\t\tif perr != nil {\n\t\t\t\treturn errors.Errorf(\"Invalid value for 'ef' in similar_to: %q\", v)\n\t\t\t}\n\t\t\tif n <= 0 {\n\t\t\t\treturn errors.Errorf(\"Value for 'ef' must be positive, got: %d\", n)\n\t\t\t}\n\t\t\tfc.vsEfOverride = int(n)\n\t\tcase \"distance_threshold\":\n\t\t\tf, perr := strconv.ParseFloat(v, 64)\n\t\t\tif perr != nil {\n\t\t\t\treturn errors.Errorf(\"Invalid value for 'distance_threshold' in similar_to: %q\", v)","sourceCodeStart":2774,"sourceCodeEnd":2810,"githubUrl":"https://github.com/dgraph-io/dgraph/blob/759e242be62c91f8d084da06ad0c8d21256d9c07/worker/task.go#L2774-L2810","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Inspect the similar_to option string in the failing query and remove the duplicated key, keeping a single 'ef' / 'distance_threshold' entry.","If you need to change the value, replace the earlier occurrence instead of appending a second pair.","If the option string is built by code, de-duplicate keys (e.g. a map) before serializing."],"exampleFix":"// before\nquery += \"; ef: 100; ef: 200\"\n// after\nquery += \"; ef: 200\"","handlingStrategy":"validation","validationCode":"keys := strings.Split(optString, \";\")\nseen := map[string]bool{}\nfor _, kv := range keys {\n    parts := strings.SplitN(kv, \":\", 2)\n    if len(parts) != 2 { continue }\n    k := strings.TrimSuffix(strings.TrimSpace(parts[0]), \":\")\n    if seen[k] { return fmt.Errorf(\"duplicate similar_to key: %s\", k) }\n    seen[k] = true\n}","typeGuard":null,"tryCatchPattern":"var parseErr *ErrSimilarToOptions\nif err := runQuery(ctx); err != nil && errors.As(err, &parseErr) {\n    // surface the offending duplicate key to the caller\n    return fmt.Errorf(\"fix similar_to options: %w\", err)\n}","preventionTips":["Build similar_to options from a map (which de-duplicates keys) rather than string concatenation.","Deduplicate option pairs before serializing in query builders.","Review copy-pasted query option strings for repeated keys."],"tags":["dql","query-options","parsing","validation"],"backgroundTag":"duplicate-option-key","analyzedSha":"759e242be62c91f8d084da06ad0c8d21256d9c07","analyzedAt":"2026-09-01T14:42:12.034Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}