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

  1. Remove @unique from the non-string/non-int predicate.
  2. Move uniqueness enforcement to the application layer (check-then-set inside a transaction) for other types.
  3. 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

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


AI-assisted analysis of dgraph-io/dgraph@759e242be6 (2026-09-01). Data as JSON: /api/errors/639d4149422f2bc8. Report an issue: GitHub.