dgraph-io/dgraph · error
there are duplicates in existing data for predicate [%v].Ple
Error message
there are duplicates in existing data for predicate [%v].Please drop the unique constraint and re-add it after fixing the predicate data
What it means
After adding a @unique constraint (or while validating a unique mutation), Dgraph compares the unique-check query results with the mutation triple. If the eq(value) query returns more than one UID, the existing data already violates uniqueness — two nodes share the value — so Dgraph cannot enforce the constraint and asks you to drop the @unique directive, fix the data, and re-add it. This is thrown during verifyUnique (edgraph/server.go:1845).
Source
Thrown at edgraph/server.go:1845
return nil
})
if err != nil {
return err
}
continue
} else {
predValue = val.Value
}
} else {
predValue = dql.TypeValFrom(pred.ObjectValue).Value
}
// Here, we check the uniqueness of the triple by comparing the result of the uniqueQuery with the triple.
if !isEmpty(queryResult.Uids) {
if len(queryResult.Uids.Uids) > 1 {
glog.Errorf("unique constraint violated for predicate [%v].uids: [%v].namespace: [%v]",
pred.Predicate, queryResult.Uids.Uids, pred.Namespace)
return errors.Errorf("there are duplicates in existing data for predicate [%v]."+
"Please drop the unique constraint and re-add it after fixing the predicate data", pred.Predicate)
} else if queryResult.Uids.Uids[0] != subjectUid {
// Determine whether the mutation is a swap mutation
isSwap, err := isSwap(qc, queryResult.Uids.Uids[0], pred.Predicate)
if err != nil {
return err
}
if !isSwap {
return errors.Errorf("could not insert duplicate value [%v] for predicate [%v]",
predValue, pred.Predicate)
}
}
}
}
return nil
}
// addQueryIfUnique adds dummy queries in the request for checking whether predicate is unique in the dbView on GitHub (pinned to 759e242be6)
Solutions
- Drop the unique constraint: `ALTER { "drop_attr": ... }` or re-alter the schema without @unique
- Find duplicates with a query like `{ q(func: has(P)) { P uid } }` (or group by value) and delete/merge duplicates so each value appears on exactly one node
- Re-apply the ALTER adding @unique after the data is deduplicated
- Prevent recurrence: enforce app-level checks or use upsert blocks for all writers; consider `@upsert` directive so conflicting concurrent mutations abort
Example fix
# before (data has two nodes with email a@b.com; mutation triggers error)
mutation { set { _:u <email> "a@b.com" . } }
# after
# 1. alter schema without @unique
# 2. query duplicates: { dups(func: eq(email, "a@b.com")) { uid } } -> delete extras
# 3. alter schema back with @unique, then run the mutation via upsert Defensive patterns
Strategy: validation
Validate before calling
// Before adding @unique (or before mutations), find duplicates:
q := `{
dup(func: has(email)) { uid email }
}`
// post-process results: flag values appearing on >1 uid; delete/merge them first Try / catch
err := runMutation(ctx, mu)
if err != nil && strings.Contains(err.Error(), "duplicates in existing data") {
// abort pipeline; run dedup job before retrying
} Prevention
- Check data for duplicates before ALTERing @unique onto an existing predicate
- Run dedup jobs after bulk imports and before enabling constraints
- Avoid seeding with blank nodes more than once
- Enable @upsert on predicates requiring strict uniqueness across concurrent writers
When it happens
Trigger: Submitting a mutation touching predicate P with @unique where the unique-check query `func: eq(P, value)` matches 2+ existing UIDs, i.e. the database already contains duplicate values for P, so the constraint cannot be validated against this mutation.
Common situations: Applying an ALTER that adds @unique to a predicate whose data already has duplicates (the schema change succeeds but subsequent mutations hit this); an index backfill or data import created duplicates; running the same seed mutation with blank nodes twice; multi-writer workloads that inserted duplicates before the unique check existed (e.g. upgrading from an older Dgraph version without @unique enforcement).
Related errors
- index for predicate [%v] is missing, add either hash or exac
- index for predicate [%v] is missing, add int index with @uni
- @unique directive not supported on [%v] type predicate
- 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/d2ca0dc0035ee36e.
Report an issue: GitHub.