dgraph-io/dgraph · error
invalid UID with value 0
Error message
invalid UID with value 0
What it means
addIndexMutations validates that the incoming DirectedEdge has a non-zero Entity (source UID) before performing any index writes. A UID of 0 is meaningless in Dgraph (UIDs start at 1), so an edge with Entity == 0 cannot be indexed and the whole mutation is rejected with 'invalid UID with value 0'.
Source
Thrown at posting/index.go:100
// TODO - See if we need to pass op as argument as t should already have Op.
func (txn *Txn) addIndexMutations(ctx context.Context, info *indexMutationInfo) ([]*pb.DirectedEdge, error) {
if info.tokenizers == nil {
info.tokenizers = schema.State().Tokenizer(ctx, info.edge.Attr)
}
if info.factorySpecs == nil {
specs, err := schema.State().FactoryCreateSpec(ctx, info.edge.Attr)
if err != nil {
return nil, err
}
info.factorySpecs = specs
}
attr := info.edge.Attr
uid := info.edge.Entity
if uid == 0 {
return []*pb.DirectedEdge{}, errors.New("invalid UID with value 0")
}
if len(info.factorySpecs) > 0 {
inKey := x.DataKey(info.edge.Attr, uid)
pl, err := txn.Get(inKey)
if err != nil {
return []*pb.DirectedEdge{}, err
}
data, err := pl.AllValues(txn.StartTs)
if err != nil {
return []*pb.DirectedEdge{}, err
}
if info.op == pb.DirectedEdge_DEL &&
len(data) > 0 && data[0].Tid == types.VFloatID {
// TODO look into better alternatives
// The issue here is that we will create dead nodes in the Vector Index
// assuming an HNSW index type. What we should do instead is invokeView on GitHub (pinned to 759e242be6)
Solutions
- Set edge.Entity to the real UID obtained from the query or from assigning UIDs via the zero/blank-node flow
- If using RDF with blank nodes ( _:alice ), let Dgraph assign UIDs instead of sending 0
- Add a caller-side check: reject edges with Entity == 0 before submitting the mutation
- For deletes with '*' as subject, use the wildcard-delete API rather than constructing an Entity=0 edge
Example fix
// before
edge := &pb.DirectedEdge{Attr: "name", Value: []byte("Alice"), ValueType: pb.Posting_STRING}
// Entity is 0 -> invalid UID with value 0
// after
edge := &pb.DirectedEdge{Entity: 0x1001, Attr: "name", Value: []byte("Alice"), ValueType: pb.Posting_STRING} Defensive patterns
Strategy: validation
Validate before calling
func validEdge(e *pb.DirectedEdge) bool {
return e != nil && e.Entity != 0 && e.Attr != ""
}
if !validEdge(edge) {
return fmt.Errorf("refusing to submit mutation: UID must be non-zero")
} Type guard
func hasUID(e *pb.DirectedEdge) bool { return e != nil && e.Entity > 0 } Try / catch
err := AddMutationWithIndex(ctx, edge, startTs)
if err != nil && strings.Contains(err.Error(), "invalid UID with value 0") {
return fmt.Errorf("edge for attr %q has Entity=0; fetch or assign a UID first", edge.Attr)
} Prevention
- Always obtain UIDs from a query or the UID assignment flow before building edges
- Never hand-set Entity to 0; use blank nodes (_:name) in RDF so Dgraph assigns UIDs
- Add unit-test assertions that all constructed edges carry a positive Entity
- For wildcard deletes, use the dedicated delete-all/wildcard APIs instead of Entity=0 edges
When it happens
Trigger: Calling AddMutationWithIndex (or the internal anonymous caller) with a DirectedEdge whose Entity field is 0 — typically an edge constructed without setting Entity, or a JSON/RDF mutation referencing the special '*' or a blank-node that failed UID assignment.
Common situations: Hand-constructed DirectedEdge structs in Go code missing Entity; RDF N-Quads with blank nodes that resolved to 0; client code building mutations programmatically and leaving the subject unset.
Related errors
- UID must to be greater than 0
- Cannot index attribute %s of type object.
- Attribute %s is not indexed.
- Index not allowed on predicate of type uid on predicate %s
- Input for predicate %q of type uid is scalar. Edge: %v
AI-assisted analysis of dgraph-io/dgraph@759e242be6 (2026-09-01).
Data as JSON: /api/errors/833d39010ffe7461.
Report an issue: GitHub.