{"record":{"id":"2183e981a1fbf559","repo":"dgraph-io/dgraph","slug":"malformed-option-in-similar-to-empty-key","errorCode":null,"errorMessage":"Malformed option in similar_to: empty key","messagePattern":"Malformed option in similar_to: empty key","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"worker/task.go","lineNumber":2789,"sourceCode":"\n// parseSimilarToOptions parses named options passed after similar_to 2 mandatory args (k, vecOrUid)\n// The parser encodes these as key/value pairs: [\"ef\", \"64\", \"distance_threshold\", \"0.5\", ...]\nfunc 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\":","sourceCodeStart":2771,"sourceCodeEnd":2807,"githubUrl":"https://github.com/dgraph-io/dgraph/blob/759e242be62c91f8d084da06ad0c8d21256d9c07/worker/task.go#L2771-L2807","documentation":"While parsing similar_to options, each key is trimmed (and a trailing colon removed); if the resulting key is an empty string, the option pair is meaningless and the parser rejects it with this error.","triggerScenarios":"Options like similar_to(a, 10, [v], \"\", \"64\") or \":\", \"0.5\" — a key that is empty or only a colon.","commonSituations":"Interpolation failures leaving an empty key in generated queries (e.g. ${key} empty); stray commas producing empty tokens; copy-paste of option blocks with a dangling colon.","solutions":["Provide a non-empty key name for every option pair (ef, distance_threshold, etc.).","Inspect the rendered query for empty placeholders from string interpolation.","Remove stray commas or lone colons from the option list."],"exampleFix":"// before\nq(func: similar_to(a, 10, [0.1,0.2], \"\", \"64\"))\n// after\nq(func: similar_to(a, 10, [0.1,0.2], \"ef\", \"64\"))","handlingStrategy":"validation","validationCode":"function validateSimilarToKeys(pairs) {\n  for (const [k] of pairs) {\n    const key = k.toLowerCase().trim().replace(/:$/, \"\");\n    if (!key) throw new Error(\"similar_to option key cannot be empty\");\n  }\n}","typeGuard":null,"tryCatchPattern":"try {\n  return await txn.query(query);\n} catch (e) {\n  if (/empty key/.test(String(e))) {\n    // fix interpolation and rebuild options\n  }\n  throw e;\n}","preventionTips":["Check template interpolation leaves no empty option keys.","Trim and validate option keys before query construction.","Avoid lone colons or dangling commas in option lists."],"tags":["dgraph","vector","similar-to","options"],"backgroundTag":"malformed-function-options","analyzedSha":"759e242be62c91f8d084da06ad0c8d21256d9c07","analyzedAt":"2026-09-01T14:42:12.034Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}