{"record":{"id":"6dc705302945b807","repo":"dgraph-io/dgraph","slug":"attribute-s-does-not-have-proper-index-for-compar","errorCode":null,"errorMessage":"Attribute:%s does not have proper index for comparison","messagePattern":"Attribute:(.+?) does not have proper index for comparison","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"worker/tokens.go","lineNumber":106,"sourceCode":"\tfor _, t := range tokenizers {\n\t\t// If function is eq and we found a tokenizer that's !Lossy(), lets return it\n\t\tswitch f {\n\t\tcase \"eq\":\n\t\t\t// For equality, find a non-lossy tokenizer.\n\t\t\tif !t.IsLossy() {\n\t\t\t\treturn t, nil\n\t\t\t}\n\t\tdefault:\n\t\t\t// rest of the cases: ge, gt, le, lt require a sortable tokenizer.\n\t\t\tif t.IsSortable() {\n\t\t\t\treturn t, nil\n\t\t\t}\n\t\t}\n\t}\n\n\t// Should we return an error if we don't find a non-lossy tokenizer for eq function.\n\tif f != \"eq\" {\n\t\treturn nil, errors.Errorf(\"Attribute:%s does not have proper index for comparison\", attr)\n\t}\n\n\t// If we didn't find a !isLossy() tokenizer for eq function on string type predicates,\n\t// then let's see if we can find a non-trigram tokenizer\n\tif typ, err := schema.State().TypeOf(attr); err == nil && typ == types.StringID {\n\t\tfor _, t := range tokenizers {\n\t\t\tif t.Identifier() != tok.IdentTrigram {\n\t\t\t\treturn t, nil\n\t\t\t}\n\t\t}\n\t}\n\n\t// otherwise, lets return the first one.\n\treturn tokenizers[0], nil\n}\n\n// pickFactoryCreateSpec(ctx, attr) will find the FactoryCreateSpec (i.e.,\n// index name + options) for the given attribute \"attr\".","sourceCodeStart":88,"sourceCodeEnd":124,"githubUrl":"https://github.com/dgraph-io/dgraph/blob/759e242be62c91f8d084da06ad0c8d21256d9c07/worker/tokens.go#L88-L124","documentation":"For inequality comparison functions (lt, le, gt, ge), pickTokenizer must find a non-lossy tokenizer; lossy tokenizers (like term or trigram) cannot support ordered comparisons. If none of the attribute's tokenizers qualifies and the function is not 'eq', this error is thrown, meaning the attribute lacks a suitable index for the requested comparison.","triggerScenarios":"Running inequality queries like 'ge(name, \"m\")' on a string predicate indexed only with a lossy tokenizer (term, trigram, or hash) instead of exact; or comparing on predicates whose index type cannot order values for the requested function.","commonSituations":"String predicates indexed with @index(term) or @index(trigram) and then queried with lt/gt/le/ge; assuming any string index supports range comparisons; schemas migrated from eq-only usage to range queries without adding an exact (or appropriate) index.","solutions":["Add an exact index (or the appropriate ordered index for the type) to the predicate: e.g. 'name: string @index(exact) .' and reindex.","For eq-style matching, use the eq function so a non-lossy tokenizer can be selected.","If only trigram is intended for fuzzy search, avoid range comparisons on that predicate."],"exampleFix":"// before\nage_index: string @index(term) .\n// queried: ge(age_index, \"m\")\n// after\nage_index: string @index(exact, term) .","handlingStrategy":"validation","validationCode":"// ensure the predicate has an exact (non-lossy) index before range queries\nschemaResp, _ := dg.Query(ctx, `schema(pred: \"name\") {}`)\n// verify schemaResp contains @index(exact) before issuing ge/lt/le/gt queries","typeGuard":null,"tryCatchPattern":"if err := runQuery(ctx); err != nil && strings.Contains(err.Error(), \"does not have proper index for comparison\") {\n    return fmt.Errorf(\"add @index(exact) (or type-appropriate ordered index) before range queries: %w\", err)\n}","preventionTips":["Use exact index for string predicates you will range-compare.","Do not assume term/trigram indexes support lt/gt/le/ge.","Review index requirements whenever a query's comparison functions change."],"tags":["dgraph","schema","indexing","inequality"],"backgroundTag":"missing-index-for-comparison","analyzedSha":"759e242be62c91f8d084da06ad0c8d21256d9c07","analyzedAt":"2026-09-01T14:42:12.034Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}