{"record":{"id":"e96dacdeee0a769c","repo":"dgraph-io/dgraph","slug":"tokenizer-must-be-specified-while-indexing-a-predi","errorCode":null,"errorMessage":"Tokenizer must be specified while indexing a predicate: %+v","messagePattern":"Tokenizer must be specified while indexing a predicate: %\\+v","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"worker/mutation.go","lineNumber":394,"sourceCode":"\t}\n\treturn false\n}\nfunc checkSchema(s *pb.SchemaUpdate) error {\n\tif s == nil {\n\t\treturn errors.Errorf(\"Nil schema\")\n\t}\n\n\tif x.ParseAttr(s.Predicate) == \"\" {\n\t\treturn errors.Errorf(\"No predicate specified in schema mutation\")\n\t}\n\n\tif x.IsInternalPredicate(s.Predicate) {\n\t\treturn errors.Errorf(\"Cannot create user-defined predicate with internal name %s\",\n\t\t\tx.ParseAttr(s.Predicate))\n\t}\n\n\tif s.Directive == pb.SchemaUpdate_INDEX && !schema.HasTokenizerOrVectorIndexSpec(s) {\n\t\treturn errors.Errorf(\"Tokenizer must be specified while indexing a predicate: %+v\", s)\n\t}\n\n\tif schema.HasTokenizerOrVectorIndexSpec(s) && s.Directive != pb.SchemaUpdate_INDEX {\n\t\treturn errors.Errorf(\"Directive must be SchemaUpdate_INDEX when a tokenizer is specified\")\n\t}\n\n\ttyp := types.TypeID(s.ValueType)\n\tif typ == types.UidID && s.Directive == pb.SchemaUpdate_INDEX {\n\t\t// index on uid type\n\t\treturn errors.Errorf(\"Index not allowed on predicate of type uid on predicate %s\",\n\t\t\tx.ParseAttr(s.Predicate))\n\t} else if typ != types.UidID && s.Directive == pb.SchemaUpdate_REVERSE {\n\t\t// reverse on non-uid type\n\t\treturn errors.Errorf(\"Cannot reverse for non-uid type on predicate %s\",\n\t\t\tx.ParseAttr(s.Predicate))\n\t}\n\n\t// If schema update has upsert directive, it should have index directive.","sourceCodeStart":376,"sourceCodeEnd":412,"githubUrl":"https://github.com/dgraph-io/dgraph/blob/759e242be62c91f8d084da06ad0c8d21256d9c07/worker/mutation.go#L376-L412","documentation":"checkSchema in worker/mutation.go validates schema mutations before proposing them to the cluster. When a schema update carries Directive == SchemaUpdate_INDEX (i.e. the predicate is being (re)indexed), at least one tokenizer (or a vector index spec) must also be supplied. Dgraph refuses an index directive with no tokenizer because it cannot build an index without knowing how to tokenize values.","triggerScenarios":"Sending a schema (via ALTER / client.Alter / runSchemaMutation / createSchema) with '@index' on a predicate but no tokenizer arguments, e.g. 'name: string @index .' without the tokenizer, or building a pb.SchemaUpdate with Directive: pb.SchemaUpdate_INDEX and an empty Tokenizer slice and no vector index spec.","commonSituations":"Hand-written DQL schema blocks where '@index' is written without parentheses/tokenizer; programmatic schema generation that sets Directive but forgets to append Tokenizers; copying a schema and stripping tokenizers while keeping @index; upgrading from a schema that had a default tokenizer assumption.","solutions":["Add a tokenizer to the predicate, e.g. 'name: string @index(hash)' or set s.Tokenizer = []string{\"hash\"} in the pb.SchemaUpdate.","If indexing is not actually needed, drop the @index directive entirely (leave Directive unset / remove @index from the schema line).","For vector predicates, supply a vector index spec (e.g. @index(hnsw(metric:\"euclidean\"))) so HasTokenizerOrVectorIndexSpec passes.","Validate the schema locally with schema.Parse or a dry run before proposing the mutation."],"exampleFix":"// before\nname: string @index .\n// after\nname: string @index(hash) .","handlingStrategy":"validation","validationCode":"func validateIndexDirective(s *pb.SchemaUpdate) error {\n    if s.Directive == pb.SchemaUpdate_INDEX && !schema.HasTokenizerOrVectorIndexSpec(s) {\n        return fmt.Errorf(\"predicate %s: @index requires a tokenizer\", s.Predicate)\n    }\n    return nil\n}","typeGuard":"func hasTokenizer(s *pb.SchemaUpdate) bool {\n    return len(s.Tokenizer) > 0\n}","tryCatchPattern":"err := dgraph.Alter(ctx, op)\nif err != nil && strings.Contains(err.Error(), \"Tokenizer must be specified\") {\n    // fix schema: add tokenizer or drop @index, then retry\n}","preventionTips":["Always pair @index with a tokenizer in parentheses","Lint DQL schema files for @index without tokenizer","Unit-test generated schemas against checkSchema"],"tags":["dgraph","schema","indexing","tokenizer"],"backgroundTag":"schema-validation-failed","analyzedSha":"759e242be62c91f8d084da06ad0c8d21256d9c07","analyzedAt":"2026-09-01T14:42:12.034Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}