{"record":{"id":"e062426aae572a72","repo":"dgraph-io/dgraph","slug":"index-for-predicate-v-is-missing-add-either-ha","errorCode":null,"errorMessage":"index for predicate [%v] is missing, add either hash or exact index with @unique","messagePattern":"index for predicate \\[(.+?)\\] is missing, add either hash or exact index with @unique","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"worker/mutation.go","lineNumber":487,"sourceCode":"\t\tif prevSchema.Upsert && !currentSchema.Upsert {\n\t\t\treturn errors.Errorf(\"could not drop @upsert from [%v] predicate when @unique directive specified\",\n\t\t\t\tx.ParseAttr(currentSchema.Predicate))\n\t\t}\n\n\t\tif prevSchema.Unique && !validTokenizer(currentSchema.Tokenizer) {\n\t\t\treturn errors.Errorf(\"could not drop index %v from [%v] predicate when @unique directive specified\",\n\t\t\t\tprevSchema.Tokenizer, x.ParseAttr(currentSchema.Predicate))\n\t\t}\n\t}\n\tif !currentSchema.Upsert {\n\t\tcurrentSchema.Upsert = true\n\t}\n\tswitch currentSchema.ValueType {\n\tcase pb.Posting_STRING:\n\t\tif len(currentSchema.Tokenizer) == 0 ||\n\t\t\t(len(currentSchema.Tokenizer) > 0 && !validTokenizer(currentSchema.Tokenizer)) {\n\n\t\t\treturn errors.Errorf(\"index for predicate [%v] is missing, add either hash or exact index with @unique\",\n\t\t\t\tx.ParseAttr(currentSchema.Predicate))\n\t\t} else {\n\t\t\treturn nil\n\t\t}\n\n\tcase pb.Posting_INT:\n\t\tif len(currentSchema.Tokenizer) == 0 {\n\t\t\treturn errors.Errorf(\"index for predicate [%v] is missing, add int index with @unique\",\n\t\t\t\tx.ParseAttr(currentSchema.Predicate))\n\t\t} else {\n\t\t\treturn nil\n\t\t}\n\t}\n\n\treturn errors.Errorf(\"@unique directive not supported on [%v] type predicate\", currentSchema.ValueType.String())\n}\n\n// ValidateAndConvert checks compatibility or converts to the schema type if the storage type is","sourceCodeStart":469,"sourceCodeEnd":505,"githubUrl":"https://github.com/dgraph-io/dgraph/blob/759e242be62c91f8d084da06ad0c8d21256d9c07/worker/mutation.go#L469-L505","documentation":"Dgraph requires that any predicate declared with @unique in the schema carries an index. For string predicates the tokenizer must be a unique-capable one (hash or exact); if the tokenizer list is empty or contains only non-unique tokenizers (e.g. term, fulltext), validateSchemaForUnique rejects the schema update because uniqueness enforcement is impossible without such an index.","triggerScenarios":"Submitting a schema (via /alter or Alter operation) that sets @unique on a string predicate while the predicate has no tokenizer at all, or has tokenizers like 'term'/'fulltext' that are not hash/exact. Raised by checkSchema -> validateSchemaForUnique.","commonSituations":"Adding @unique to an existing string predicate that was previously only indexed with 'term' or 'fulltext' for search; forgetting to add an index when first declaring the unique constraint; copying a schema between environments where index directives were stripped.","solutions":["Change the schema to add a unique-capable tokenizer, e.g. `name string @index(hash) @unique .` or `@index(exact) @unique`.","Drop the @unique directive if uniqueness is not actually required and keep the existing tokenizer.","Re-run the alter after fixing the schema definition."],"exampleFix":"// before (fails)\nemail string @index(term) @unique .\n\n// after\nemail string @index(hash) @unique .","handlingStrategy":"validation","validationCode":"# Before altering, ensure string @unique predicates have hash or exact index\n# schema rule check (DQL/GraphQL alter schema):\n# email string @index(hash) @unique .\nfor pred in schemaChanges:\n    if pred.unique and pred.type == 'string':\n        valid = {'hash', 'exact'}\n        toks = set(pred.index or [])\n        if not toks & valid:\n            raise ValueError(f\"{pred.name}: add @index(hash) or @index(exact) with @unique\")","typeGuard":null,"tryCatchPattern":"// Go client\nerr := dg.Alter(ctx, op)\nif err != nil && strings.Contains(err.Error(), \"index for predicate\") {\n    // fix schema: add @index(hash)/@index(exact) next to @unique and retry\n}","preventionTips":["Always pair @unique with @index(hash) or @index(exact) for strings and @index(int) for ints.","Validate schema files in CI by running them against a scratch Dgraph instance.","Never downgrade a unique index tokenizer (hash/exact) to term/fulltext."],"tags":["dgraph","schema","unique-constraint","indexing"],"backgroundTag":"missing-unique-index","analyzedSha":"759e242be62c91f8d084da06ad0c8d21256d9c07","analyzedAt":"2026-09-01T14:42:12.034Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}