dgraph-io/dgraph · error

Attribute:%s does not have proper index for comparison

Error message

Attribute:%s does not have proper index for comparison

What it means

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.

Source

Thrown at worker/tokens.go:106

	for _, t := range tokenizers {
		// If function is eq and we found a tokenizer that's !Lossy(), lets return it
		switch f {
		case "eq":
			// For equality, find a non-lossy tokenizer.
			if !t.IsLossy() {
				return t, nil
			}
		default:
			// rest of the cases: ge, gt, le, lt require a sortable tokenizer.
			if t.IsSortable() {
				return t, nil
			}
		}
	}

	// Should we return an error if we don't find a non-lossy tokenizer for eq function.
	if f != "eq" {
		return nil, errors.Errorf("Attribute:%s does not have proper index for comparison", attr)
	}

	// If we didn't find a !isLossy() tokenizer for eq function on string type predicates,
	// then let's see if we can find a non-trigram tokenizer
	if typ, err := schema.State().TypeOf(attr); err == nil && typ == types.StringID {
		for _, t := range tokenizers {
			if t.Identifier() != tok.IdentTrigram {
				return t, nil
			}
		}
	}

	// otherwise, lets return the first one.
	return tokenizers[0], nil
}

// pickFactoryCreateSpec(ctx, attr) will find the FactoryCreateSpec (i.e.,
// index name + options) for the given attribute "attr".

View on GitHub (pinned to 759e242be6)

Solutions

  1. Add an exact index (or the appropriate ordered index for the type) to the predicate: e.g. 'name: string @index(exact) .' and reindex.
  2. For eq-style matching, use the eq function so a non-lossy tokenizer can be selected.
  3. If only trigram is intended for fuzzy search, avoid range comparisons on that predicate.

Example fix

// before
age_index: string @index(term) .
// queried: ge(age_index, "m")
// after
age_index: string @index(exact, term) .
Defensive patterns

Strategy: validation

Validate before calling

// ensure the predicate has an exact (non-lossy) index before range queries
schemaResp, _ := dg.Query(ctx, `schema(pred: "name") {}`)
// verify schemaResp contains @index(exact) before issuing ge/lt/le/gt queries

Try / catch

if err := runQuery(ctx); err != nil && strings.Contains(err.Error(), "does not have proper index for comparison") {
    return fmt.Errorf("add @index(exact) (or type-appropriate ordered index) before range queries: %w", err)
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


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