{"record":{"id":"c1b17fa681633c1d","repo":"dgraph-io/dgraph","slug":"could-not-drop-index-v-from-v-predicate-when","errorCode":null,"errorMessage":"could not drop index %v from [%v] predicate when @unique directive specified","messagePattern":"could not drop index (.+?) from \\[(.+?)\\] predicate when @unique directive specified","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"worker/mutation.go","lineNumber":475,"sourceCode":"}\n\nfunc validateSchemaForUnique(prevSchema pb.SchemaUpdate, currentSchema *pb.SchemaUpdate) error {\n\tvalidTokenizer := func(tokenizers []string) bool {\n\t\tfor _, value := range tokenizers {\n\t\t\tif value == \"hash\" || value == \"exact\" || value == \"int\" {\n\t\t\t\treturn true\n\t\t\t}\n\t\t}\n\t\treturn false\n\t}\n\tif prevSchema.Predicate != \"\" {\n\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:","sourceCodeStart":457,"sourceCodeEnd":493,"githubUrl":"https://github.com/dgraph-io/dgraph/blob/759e242be62c91f8d084da06ad0c8d21256d9c07/worker/mutation.go#L457-L493","documentation":"Companion to the @upsert rule: a predicate already marked @unique must retain a valid index tokenizer across alterations, because uniqueness is enforced through the index. validateSchemaForUnique rejects updates where prevSchema.Unique is true but validTokenizer(currentSchema.Tokenizer) is false (tokenizer removed or replaced with nothing).","triggerScenarios":"Altering a '@unique' predicate by removing or invalidating its tokenizer, e.g. 'email: string @index(hash) @unique' changed to 'email: string @unique' or to an unsupported/empty tokenizer list.","commonSituations":"Switching tokenizers on a unique field without keeping a valid one; stripping @index during schema normalization; tooling that regenerates schemas and drops tokenizer arrays.","solutions":["Keep a valid tokenizer: e.g. 'email: string @index(hash) @upsert @unique'.","If changing tokenizers, supply a replacement valid tokenizer in the same alteration rather than an empty list.","Remove @unique (and @upsert) in the same update if the index is no longer wanted.","Check the accepted tokenizer list (types and tokenizer names) for the predicate's value type before proposing the change."],"exampleFix":"// before\nemail: string @upsert @unique .\n// after\nemail: string @index(hash) @upsert @unique .","handlingStrategy":"validation","validationCode":"func validateUniqueTokenizer(prev, next *pb.SchemaUpdate) error {\n    if prev != nil && prev.Predicate != \"\" && prev.Unique && len(next.Tokenizer) == 0 {\n        return fmt.Errorf(\"predicate %s: @unique requires a valid index tokenizer\", next.Predicate)\n    }\n    return nil\n}","typeGuard":null,"tryCatchPattern":"err := dgraph.Alter(ctx, op)\nif err != nil && strings.Contains(err.Error(), \"could not drop index\") {\n    // supply a valid tokenizer (or remove @unique) and retry\n}","preventionTips":["Never regenerate @unique predicates without a tokenizer","When changing tokenizers, always provide the new list in the same alteration","Keep a schema test asserting unique preds retain tokenizers"],"tags":["dgraph","schema","unique","indexing"],"backgroundTag":"schema-validation-failed","analyzedSha":"759e242be62c91f8d084da06ad0c8d21256d9c07","analyzedAt":"2026-09-01T14:42:12.034Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}