dgraph-io/dgraph · error

Directive must be SchemaUpdate_INDEX when a tokenizer is spe

Error message

Directive must be SchemaUpdate_INDEX when a tokenizer is specified

What it means

This is the mirror check of the tokenizer rule: if a schema update specifies tokenizers (or a vector index spec) via HasTokenizerOrVectorIndexSpec, the Directive must be SchemaUpdate_INDEX. Dgraph throws it because tokenizers are meaningless without an index being built, so it treats tokenizer-without-@index as an invalid schema.

Source

Thrown at worker/mutation.go:398

	if s == nil {
		return errors.Errorf("Nil schema")
	}

	if x.ParseAttr(s.Predicate) == "" {
		return errors.Errorf("No predicate specified in schema mutation")
	}

	if x.IsInternalPredicate(s.Predicate) {
		return errors.Errorf("Cannot create user-defined predicate with internal name %s",
			x.ParseAttr(s.Predicate))
	}

	if s.Directive == pb.SchemaUpdate_INDEX && !schema.HasTokenizerOrVectorIndexSpec(s) {
		return errors.Errorf("Tokenizer must be specified while indexing a predicate: %+v", s)
	}

	if schema.HasTokenizerOrVectorIndexSpec(s) && s.Directive != pb.SchemaUpdate_INDEX {
		return errors.Errorf("Directive must be SchemaUpdate_INDEX when a tokenizer is specified")
	}

	typ := types.TypeID(s.ValueType)
	if typ == types.UidID && s.Directive == pb.SchemaUpdate_INDEX {
		// index on uid type
		return errors.Errorf("Index not allowed on predicate of type uid on predicate %s",
			x.ParseAttr(s.Predicate))
	} else if typ != types.UidID && s.Directive == pb.SchemaUpdate_REVERSE {
		// reverse on non-uid type
		return errors.Errorf("Cannot reverse for non-uid type on predicate %s",
			x.ParseAttr(s.Predicate))
	}

	// If schema update has upsert directive, it should have index directive.
	if s.Upsert && len(s.Tokenizer) == 0 && !s.Unique {
		return errors.Errorf("Index tokenizer is mandatory for: [%s] when specifying @upsert directive",
			x.ParseAttr(s.Predicate))
	}

View on GitHub (pinned to 759e242be6)

Solutions

  1. Add the @index directive back: 'name: string @index(hash)' or set s.Directive = pb.SchemaUpdate_INDEX.
  2. If indexing is not wanted, remove the tokenizer as well, e.g. 'name: string' or s.Tokenizer = nil.
  3. Make Directive and Tokenizer consistent in code by deriving Directive from whether Tokenizer is non-empty.
  4. Validate the schema with checkSchema/TestCheckSchema-style logic in unit tests before shipping the mutation.

Example fix

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

Strategy: validation

Validate before calling

func validateTokenizerDirective(s *pb.SchemaUpdate) error {
    if schema.HasTokenizerOrVectorIndexSpec(s) && s.Directive != pb.SchemaUpdate_INDEX {
        return fmt.Errorf("predicate %s: tokenizer requires @index", s.Predicate)
    }
    return nil
}

Type guard

func tokenizerConsistent(s *pb.SchemaUpdate) bool {
    has := len(s.Tokenizer) > 0
    indexed := s.Directive == pb.SchemaUpdate_INDEX
    return has == indexed
}

Try / catch

err := dgraph.Alter(ctx, op)
if err != nil && strings.Contains(err.Error(), "Directive must be SchemaUpdate_INDEX") {
    // re-set Directive to INDEX or clear Tokenizer, then retry
}

Prevention

When it happens

Trigger: Altering a predicate with tokenizers but without @index, e.g. 'name: string @hash' or a pb.SchemaUpdate with Tokenizer: ["hash"] and Directive: pb.SchemaUpdate_NONE; typically after someone removed @index but left the tokenizer, or edited the schema programmatically.

Common situations: Manual schema edits that delete '@index' but keep the tokenizer in parentheses; code that toggles indexing off by changing only the Directive field while leaving Tokenizer populated; schema merge tools that combine fields from different versions.

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