dgraph-io/dgraph · error

Tokenizers present without indexing on attr %s

Error message

Tokenizers present without indexing on attr %s

What it means

The inverse of the previous case: the schema update declares tokenizers (or a vector index spec) for a predicate but the directive is not @index. Tokenizers only make sense with an index, so resolveTokenizers rejects the update, naming the attribute. This keeps the stored schema internally consistent.

Source

Thrown at schema/parse.go:435

		if (typ == types.UidID || typ == types.DefaultID || typ == types.PasswordID) &&
			schema.Directive == pb.SchemaUpdate_INDEX {
			return errors.Errorf("Indexing not allowed on predicate %s of type %s",
				x.ParseAttr(schema.Predicate), typ.Name())
		}

		if typ == types.UidID {
			continue
		}

		if !HasTokenizerOrVectorIndexSpec(schema) &&
			schema.Directive == pb.SchemaUpdate_INDEX {
			return errors.Errorf(
				"Require type of tokenizer for pred: %s of type: %s for indexing.",
				schema.Predicate, typ.Name())
		} else if HasTokenizerOrVectorIndexSpec(schema) &&
			schema.Directive != pb.SchemaUpdate_INDEX {
			return errors.Errorf("Tokenizers present without indexing on attr %s",
				x.ParseAttr(schema.Predicate))
		}
		// check for valid tokenizer types and duplicates
		var seen = make(map[string]bool)
		var seenSortableTok bool
		for _, t := range schema.Tokenizer {
			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

View on GitHub (pinned to 759e242be6)

Solutions

  1. Add the @index directive: `pred: string @index(hash) .`
  2. Or remove the tokenizer list if the predicate should not be indexed: `pred: string .`
  3. Check any schema-generation tooling to ensure Directive=SchemaUpdate_INDEX is set whenever Tokenizer is non-empty.
  4. Re-apply the alteration.

Example fix

// before
name: string @hash .
// after
name: string @index(hash) .
Defensive patterns

Strategy: validation

Validate before calling

function requireIndexWithTokenizers(line) {
  const hasTok = /@(hash|exact|term|fulltext|trigram|int|float|datetime|geo|default)\b/.test(line);
  const hasIndex = /@index\s*\(/.test(line);
  if (hasTok && !hasIndex) throw new Error('tokenizers present without @index: ' + line);
}

Try / catch

try {
  await dgraph.Alter(ctx, op);
} catch (e) {
  if (String(e).includes('Tokenizers present without indexing')) {
    // either add @index(...) or drop the tokenizers, then retry
  }
  throw e;
}

Prevention

When it happens

Trigger: Altering schema with `pred: string @hash .` (tokenizer given without @index) or a SchemaUpdate with a non-INDEX directive but populated Tokenizer list / vector spec.

Common situations: Typos like writing `@index` wrong or omitting it while listing tokenizers; editing schema by hand and dropping the @index keyword; tooling that sets Tokenizer but forgets Directive; converting a previously indexed predicate back to non-indexed while leaving old tokenizers.

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/e379aa54f2a57dc8. Report an issue: GitHub.