Upsert not working as expected


curl localhost:8080/alter -X POST -d $'
name: string @index(term) .
email: string @index(exact) @upsert .
cc: [uid] .
age: int @index(int) .' | jq

test code

func TestZ(t *testing.T) {

	wg := &sync.WaitGroup{}

	for i := 0; i < 20; i++ {
		q := fmt.Sprintf(`query {
			q(func: eq(email, "[email protected]")) {
			  v1 as uid

		m := fmt.Sprintf(`
		  uid(v1) <name> "first last" .
		  uid(v1) <email> "[email protected]" .

		go func() {
			defer wg.Done()
			resp, err := dg.NewTxn().Do(context.Background(), &api.Request{
				Query: q,
				Mutations: []*api.Mutation{{
					SetNquads: []byte(m),
				CommitNow: true,

			_ = resp
			// if err != nil {
			// }


When TestZ first time run, it create 20 nodes with same email.

But when TestZ second time run, only 1 ok, but the others are Transaction has been aborted. Please retry (as for doc: this is what we expected)

For data pre-exist or not has different handle strategy.

Any suggest or policy for avoid creating the other 19 node when first time run?

Assuming that your code is right. Please do the following.

Erase the p, w, zw folders.

Remove this from your Schema. This is a different upsert procedure.

Try again. If that doesn’t work, I’ll review your code again to find any wrong step.


I’m using latest docker image with no data persistence.

docker pull dgraph/standalone

docker run -it --rm \
    --name dgraph \
    -p 8000:8000 \
    -p 8080:8080 \
    -p 9080:9080 \

And could u pls explain why remove @upsert ?

Opps, can not re-produce.

But remove @upsert, it has same result.

Hi @ElvizLai

  1. Start with a fresh Dgraph runtime, and try without @upsert directive on email first. You should see 20 email ids (same value) in Dgraph. You should not see any Transaction has been aborted. Please retry message. This is what you might have seen in the system.
  2. Now, drop data from Dgraph and add the @upsert directive on email. Run the test again. This time only one node will be created. The @upsert directive enforces uniqueness for the email field when running transactions concurrently. At this time, you should see Transaction has been aborted. Please retry. This is caused by the @upsert directive enforcing uniqueness on the email attribute.

Please note that the presence of an index is mandatory for @upsert to work.