dgraph-io/dgraph · error

Predicate not specified

Error message

Predicate not specified

What it means

errEmptyPredicate is returned by MovePredicate in the dgraph worker package when a move-tablet request carries an empty predicate name. Dgraph refuses to start a predicate move without an explicit predicate, since it must know which tablet/keyspace to stream between groups.

Source

Thrown at worker/predicate_move.go:35

	"github.com/golang/glog"
	"github.com/pkg/errors"
	"go.opentelemetry.io/otel/attribute"
	"go.opentelemetry.io/otel/trace"
	"google.golang.org/protobuf/proto"

	"github.com/dgraph-io/badger/v4"
	bpb "github.com/dgraph-io/badger/v4/pb"
	"github.com/dgraph-io/dgo/v250/protos/api"
	"github.com/dgraph-io/dgraph/v25/posting"
	"github.com/dgraph-io/dgraph/v25/protos/pb"
	"github.com/dgraph-io/dgraph/v25/schema"
	"github.com/dgraph-io/dgraph/v25/tok/hnsw"
	"github.com/dgraph-io/dgraph/v25/x"
	"github.com/dgraph-io/ristretto/v2/z"
)

var (
	errEmptyPredicate = errors.Errorf("Predicate not specified")
	errNotLeader      = errors.Errorf("Server is not leader of this group")
	emptyPayload      = api.Payload{}
)

// size of kvs won't be too big, we would take care before proposing.
func populateKeyValues(ctx context.Context, kvs []*bpb.KV) error {
	glog.Infof("Writing %d keys\n", len(kvs))
	if len(kvs) == 0 {
		return nil
	}
	writer := posting.NewTxnWriter(pstore)
	if err := writer.Write(&bpb.KVList{Kv: kvs}); err != nil {
		return err
	}
	if err := writer.Flush(); err != nil {
		return err
	}
	pk, err := x.Parse(kvs[0].Key)

View on GitHub (pinned to 759e242be6)

Solutions

  1. Identify the Zero request that carried the empty predicate from logs and check why tablet state has a blank pred.
  2. Restart Zero to rebuild consistent internal tablet state.
  3. If from custom tooling, ensure the MoveTablet/MovePredicate request always sets the Pred field before calling.
  4. Upgrade to a fixed Dgraph release if this arises during normal Zero rebalancing.

Example fix

// before
req := &pb.MoveTabletRequest{SourceGroupId: 1, DestGroupId: 2}
// after
req := &pb.MoveTabletRequest{SourceGroupId: 1, DestGroupId: 2, Tablet: &pb.Tablet{Predicate: "friend"}}
Defensive patterns

Strategy: validation

Validate before calling

func validateMove(req *pb.MoveTabletRequest) error {
	if req == nil || req.Tablet == nil || req.Tablet.Predicate == "" {
		return errors.New("predicate must be set before MoveTablet")
	}
	return nil
}

Type guard

func hasPredicate(t *pb.Tablet) bool {
	return t != nil && t.Predicate != ""
}

Try / catch

if err := worker.MovePredicate(ctx, pred, src, dst); err != nil {
	if strings.Contains(err.Error(), "Predicate not specified") {
		// reject the request upstream / fix Zero tablet state
	}
}

Prevention

When it happens

Trigger: Calling MovePredicate via the internal MoveTablet RPC (triggered by Zero rebalancing or `movePredicates`) with pred == "" — e.g. a malformed Zero move request or a state.json/tablet entry with a blank predicate.

Common situations: Corrupt Zero internal state proposing an empty tablet move; bugs or manual edits in Zero's tablet map; custom tooling invoking the internal move API with unset fields.

Related errors


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