dgraph-io/dgraph · error
More than one sortable index encountered for: %v
Error message
More than one sortable index encountered for: %v
What it means
Dgraph allows at most one sortable tokenizer (exact for strings, the default tokenizer for int/float/datetime) per predicate, because sorting requires a single ordering; a second sortable tokenizer would create conflicting sort orders. resolveTokenizers fails the update when a second tokenizer with IsSortable() is encountered.
Source
Thrown at schema/parse.go:460
tokenizer, has := tok.GetTokenizer(t)
if !has {
return errors.Errorf("Invalid tokenizer %s", t)
}
tokenizerType, ok := types.TypeForName(tokenizer.Type())
x.AssertTrue(ok) // Type is validated during tokenizer loading.
if tokenizerType != typ {
return errors.Errorf("Tokenizer: %s isn't valid for predicate: %s of type: %s",
tokenizer.Name(), x.ParseAttr(schema.Predicate), typ.Name())
}
if _, ok := seen[tokenizer.Name()]; !ok {
seen[tokenizer.Name()] = true
} else {
return errors.Errorf("Duplicate tokenizers present for attr %s",
x.ParseAttr(schema.Predicate))
}
if tokenizer.IsSortable() {
if seenSortableTok {
return errors.Errorf("More than one sortable index encountered for: %v",
schema.Predicate)
}
seenSortableTok = true
}
}
}
return nil
}
func parseTypeDeclaration(it *lex.ItemIterator, ns uint64) (*pb.TypeUpdate, error) {
// Iterator is currently on the token corresponding to the keyword type.
if it.Item().Typ != itemText || it.Item().Val != "type" {
return nil, it.Item().Errorf("Expected type keyword. Got %v", it.Item().Val)
}
it.Next()
if it.Item().Typ != itemText {
return nil, it.Item().Errorf("Expected type name. Got %v", it.Item().Val)View on GitHub (pinned to 759e242be6)
Solutions
- Keep exactly one sortable tokenizer (typically `exact` for sortable strings).
- Use non-sortable tokenizers (hash, term, fulltext, trigram) for matching, and `exact` only once if you need order: `@index(hash, exact) .`
- If both sorting and duplicate-free matching are needed, this combination is supported — just don't repeat sortable entries.
- Re-apply the alteration.
Example fix
// before name: string @index(exact, exact) . // after name: string @index(hash, exact) .
Defensive patterns
Strategy: validation
Validate before calling
const SORTABLE = new Set(['exact', 'int', 'float', 'datetime', 'default']);
function validateSingleSortable(tokenizers) {
const sortables = tokenizers.filter(t => SORTABLE.has(t));
if (sortables.length > 1) throw new Error('more than one sortable tokenizer: ' + sortables);
} Try / catch
try {
await dgraph.Alter(ctx, op);
} catch (e) {
if (String(e).includes('More than one sortable index')) {
// keep a single sortable tokenizer and retry
}
throw e;
} Prevention
- List at most one sortable tokenizer (exact for strings) per predicate
- Use hash/term/fulltext/trigram for matching and exact only when sorting/order is needed
- Review tooling that appends 'exact' automatically for sorting support
When it happens
Trigger: `pred: string @index(exact, exact) .` (also a duplicate) or any directive containing two sortable tokenizers, e.g. hypothetically `@index(exact, hash)` plus another sortable entry added by tooling.
Common situations: Tooling that appends an 'exact' tokenizer for sorting to a schema that already lists one; misunderstanding that multiple string tokenizers are fine but multiple sortable ones are not; generated schemas merging sort and filter requirements.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- illegal rune found "%c", expecting {
- Malformed JSON
- Require type of tokenizer for pred: %s of type: %s for index
- Tokenizers present without indexing on attr %s
- Invalid tokenizer %s
AI-assisted analysis of dgraph-io/dgraph@759e242be6 (2026-09-01).
Data as JSON: /api/errors/8ea8e79424cd3882.
Report an issue: GitHub.