dgraph-io/dgraph · error
nil vector returned
Error message
nil vector returned
What it means
errNilVector is a sentinel error in the HNSW vector-index helper returned by getVecFromUid when the vector for a UID is nil, and by PickStartNode. It means the vector-index layer expected an embedding/pvector for a node but the stored value was absent or empty.
Source
Thrown at tok/hnsw/helper.go:50
VecKeyword = "__vector_"
visitedVectorsLevel = "visited_vectors_level_"
distanceComputations = "vector_distance_computations"
searchTime = "vector_search_time"
VecEntry = "__vector_entry"
VecDead = "__vector_dead"
VectorIndexMaxLevels = 5
EfConstruction = 16
EfSearch = 12
// ByteData indicates the key stores data.
ByteData = byte(0x00)
// DefaultPrefix is the prefix used for data, index and reverse keys so that relative
DefaultPrefix = byte(0x00)
// NsSeparator is the separator between the namespace and attribute.
NsSeparator = "-"
)
var (
errNilVector = errors.New("nil vector returned")
errFetchingPostingList = errors.New("error fetching posting list")
)
type SearchResult struct {
nnUids []uint64
traversalPath []uint64
extraMetrics map[string]uint64
}
func (s *SearchResult) GetNnUids() []uint64 {
return s.nnUids
}
func (s *SearchResult) GetTraversalPath() []uint64 {
return s.traversalPath
}
func (s *SearchResult) GetExtraMetrics() map[string]uint64 {View on GitHub (pinned to 759e242be6)
Solutions
- Re-embed and re-write the vector for the affected UID(s), or delete the stale index entry
- Drop and rebuild the vector index for the predicate (drop @index(hnsw(...)) then re-apply)
- Check for interrupted writes/restore operations that left postings without vectors
- Filter affected UIDs out of the search path and log them for backfill
Example fix
// before
vec, err := getVecFromUid(ctx, uid) // errNilVector
// after
vec, err := getVecFromUid(ctx, uid)
if errors.Is(err, errNilVector) {
backfillVector(uid) // recompute embedding, then retry
vec, err = getVecFromUid(ctx, uid)
} Defensive patterns
Strategy: fallback
Validate before calling
// verify vector presence before relying on search results
vec, err := getVecFromUid(ctx, uid)
if err != nil || vec == nil {
markForBackfill(uid)
return nil
} Try / catch
res, err := hnsw.SearchWithUid(ctx, idx, uid, opts)
if err != nil {
if errors.Is(err, errNilVector) {
return backfillAndRetry(ctx, uid)
}
return err
} Prevention
- Write vectors and index entries atomically; rebuild index after restores
- Drop and recreate the HNSW index if vectors were manually deleted
- Monitor for empty/nil embeddings at ingestion time
- Backfill missing embeddings instead of letting index reads fail
When it happens
Trigger: Vector similarity search or traversal over an HNSW index where a posting/node lacks its vector payload — e.g. the embedding was never written, was deleted, or the predicate value is empty while the index entry remains.
Common situations: Partial writes where the index was built before the vector was persisted; manual deletes of the vector predicate without dropping/rebuilding the index; corrupted or truncated postings after restore/migration.
Related errors
- error creating indexer for %s: %w
- error fetching posting list
- Not allowed to insert mutations in vector index keys, edge:
- Schema state not found for %s.
- illegal rune found "%c", expecting {
AI-assisted analysis of dgraph-io/dgraph@759e242be6 (2026-09-01).
Data as JSON: /api/errors/6a7c94622550a412.
Report an issue: GitHub.