dgraph-io/dgraph · error
@unique directive not supported on [%v] type predicate
Error message
@unique directive not supported on [%v] type predicate
What it means
The @unique directive is only meaningful on string and int predicates. If the predicate's type is anything else (float, bool, datetime, uid, etc.), validateSchemaForUnique falls through the type switch and rejects the schema because Dgraph has no tokenizer/index mechanism to enforce uniqueness for that value type.
Source
Thrown at worker/mutation.go:502
if len(currentSchema.Tokenizer) == 0 ||
(len(currentSchema.Tokenizer) > 0 && !validTokenizer(currentSchema.Tokenizer)) {
return errors.Errorf("index for predicate [%v] is missing, add either hash or exact index with @unique",
x.ParseAttr(currentSchema.Predicate))
} else {
return nil
}
case pb.Posting_INT:
if len(currentSchema.Tokenizer) == 0 {
return errors.Errorf("index for predicate [%v] is missing, add int index with @unique",
x.ParseAttr(currentSchema.Predicate))
} else {
return nil
}
}
return errors.Errorf("@unique directive not supported on [%v] type predicate", currentSchema.ValueType.String())
}
// ValidateAndConvert checks compatibility or converts to the schema type if the storage type is
// specified. If no storage type is specified then it converts to the schema type.
func ValidateAndConvert(edge *pb.DirectedEdge, su *pb.SchemaUpdate) error {
if isDeletePredicateEdge(edge) {
return nil
}
if types.TypeID(edge.ValueType) == types.DefaultID && isStarAll(edge.Value) {
return nil
}
if strings.Contains(su.Predicate, hnsw.VecKeyword) {
return errors.Errorf("Not allowed to insert mutations in vector index keys, edge: [%v]", edge)
}
storageType := posting.TypeID(edge)View on GitHub (pinned to 759e242be6)
Solutions
- Remove @unique from the non-string/non-int predicate.
- Move uniqueness enforcement to the application layer (check-then-set inside a transaction) for other types.
- If a string or int representation is acceptable, change the predicate type so a hash/exact/int index can back @unique.
Example fix
// before (fails) createdAt datetime @index(hour) @unique . // after createdAt datetime @index(hour) . // enforce uniqueness in app logic or via a unique string/int surrogate key
Defensive patterns
Strategy: validation
Validate before calling
UNIQUE_OK_TYPES = {'string', 'int'}
for pred in schemaChanges:
if pred.unique and pred.type not in UNIQUE_OK_TYPES:
raise ValueError(f"@unique not supported on {pred.type} predicate {pred.name}") Try / catch
if err != nil && strings.Contains(err.Error(), "@unique directive not supported") {
// move uniqueness enforcement to application logic for this type
} Prevention
- Only use @unique on string and int predicates.
- For other scalar types, enforce uniqueness with an upsert (query-then-set) transaction.
- Document which predicates carry uniqueness invariants in the schema file.
When it happens
Trigger: Submitting an alter that puts @unique on a predicate whose schema type is not string or int, e.g. `createdAt datetime @index(hour) @unique .` or `active bool @unique .` Raised by checkSchema -> validateSchemaForUnique.
Common situations: Porting SQL UNIQUE constraints to Dgraph for date/bool/float columns; assuming @unique works on any scalar; typos in the predicate type declaration.
Related errors
- there are duplicates in existing data for predicate [%v].Ple
- index for predicate [%v] is missing, add either hash or exac
- index for predicate [%v] is missing, add int index with @uni
- illegal rune found "%c", expecting {
- JSON map is followed by illegal rune "%c"
AI-assisted analysis of dgraph-io/dgraph@759e242be6 (2026-09-01).
Data as JSON: /api/errors/639d4149422f2bc8.
Report an issue: GitHub.