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

  1. Keep exactly one sortable tokenizer (typically `exact` for sortable strings).
  2. Use non-sortable tokenizers (hash, term, fulltext, trigram) for matching, and `exact` only once if you need order: `@index(hash, exact) .`
  3. If both sorting and duplicate-free matching are needed, this combination is supported — just don't repeat sortable entries.
  4. 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

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


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