Critical Bug: node get's deleted completely, if a non-existend facet is removed


Report a Dgraph Bug

What version of Dgraph are you using?

Dgraph Version
$ dgraph version
 
v21.03.0

Have you tried reproducing the issue with the latest release?

yes

What is the hardware spec (RAM, OS)?

linux 5.10.29-1-lts, 32GB ram

Steps to reproduce the issue (command/config used to run Dgraph).

run this test:

package main

import (
	"context"
	"encoding/json"
	"fmt"
	"testing"

	"github.com/dgraph-io/dgo/v200"
	"github.com/dgraph-io/dgo/v200/protos/api"
	"github.com/stretchr/testify/require"
	"google.golang.org/grpc"
)

func Test_issue0(t *testing.T) {
	conn, err := grpc.Dial(dgraphAddr(), grpc.WithInsecure())
	if err != nil {
		t.Fatalf("conntect: %v", err)
	}

	dg := dgo.NewDgraphClient(api.NewDgraphClient(conn))
	defer dg.Alter(context.Background(), &api.Operation{DropAll: true})

	schema := `
type Node {
  name: string
}

name: string .
`

	err = dg.Alter(context.Background(), &api.Operation{Schema: schema})
	require.NoError(t, err)

	in := struct {
		Name string `json:"name,omitempty"`
		ID   string `json:"uid"`
		Type string `json:"dgraph.type"`
	}{
		ID:   "_:probe-0",
		Name: "foobar",
		Type: "Node",
	}

	js, err := json.Marshal(in)
	require.NoError(t, err)

	assigned, err := dg.NewTxn().Mutate(context.Background(), &api.Mutation{SetJson: js, CommitNow: true})
	require.NoError(t, err)

	in.ID = assigned.GetUids()["probe-0"]

	update, err := json.Marshal(map[string]interface{}{
		"uid":          in.ID,
		"doesnt|exist": nil,
	})
	require.NoError(t, err)

	_, err = dg.NewTxn().Mutate(context.Background(), &api.Mutation{DeleteJson: update, CommitNow: true})
	require.NoError(t, err)

	query := `
query {
  node(func: uid(%s)) {
    uid
    name
    dgraph.type
  }
}
`
	query = fmt.Sprintf(query, in.ID)

	resp, err := dg.NewTxn().Query(context.Background(), query)
	require.NoError(t, err)

	var data struct {
		Nodes []map[string]interface{} `json:"node"`
	}
	err = json.Unmarshal(resp.GetJson(), &data)
	require.NoError(t, err)

	require.Len(t, data.Nodes, 1)
	_, ok := data.Nodes[0]["name"]
	require.True(t, ok)
	_, ok = data.Nodes[0]["dgraph.type"]
	require.True(t, ok)
}

Expected behaviour and actual result.

expected: node is available
actual result: the node is gone.

1 Like

Thanks for letting us know @Joschka. Looks like this bug got introduced by PR #7171 that’s part of the v21.03.0 release. We’re looking into the fix for it.

@karl

1 Like

@Joschka I have implemented a fix and it is currently under review. You can watch our progress at PR #7737. Thanks again for the bug report!

1 Like