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
- Add the @index directive back: 'name: string @index(hash)' or set s.Directive = pb.SchemaUpdate_INDEX.
- If indexing is not wanted, remove the tokenizer as well, e.g. 'name: string' or s.Tokenizer = nil.
- Make Directive and Tokenizer consistent in code by deriving Directive from whether Tokenizer is non-empty.
- 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
- Derive Directive from Tokenizer presence in schema builders
- Never delete @index while keeping tokenizer arguments
- Diff old vs new schema before ALTER
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
- Require type of tokenizer for pred: %s of type: %s for index
- Tokenizers present without indexing on attr %s
- failed to enrich schema
- Tokenizer must be specified while indexing a predicate: %+v
- illegal rune found "%c", expecting {
AI-assisted analysis of dgraph-io/dgraph@759e242be6 (2026-09-01).
Data as JSON: /api/errors/fecb31582042e0b0.
Report an issue: GitHub.