weaviate/weaviate · error

get neighbor vec

Error message

get neighbor vec

What it means

Wrapped failure in reassignNeighbor when fetching the vector of a neighbor node fails with an error that is not a recoverable storobj.ErrNotFound. The cleanup worker needs the neighbor's vector to reconnect it after its tombstoned neighbor is removed; if the vector cannot be read for any reason other than 'object was deleted', the error is wrapped as 'get neighbor vec' and aborts the reassignment so the node stays in maintenance state.

Source

Thrown at adapters/repos/db/vector/hnsw/delete.go:656

	}
	neighborNode.Unlock()

	var neighborVec []float32
	var compressorDistancer compressionhelpers.CompressorDistancer
	if h.compressed.Load() {
		compressorDistancer, err = h.compressor.NewDistancerFromID(neighbor)
	} else {
		neighborVec, err = h.cache.Get(context.Background(), neighbor)
	}

	if err != nil {
		var e storobj.ErrNotFound
		if errors.As(err, &e) {
			h.handleDeletedNode(e.DocID, "reassignNeighbor")
			return true, nil
		} else {
			// not a typed error, we can recover from, return with err
			return false, errors.Wrap(err, "get neighbor vec")
		}
	}

	// the new recursive implementation no longer needs an entrypoint, so we can
	// just pass this dummy value to make the neighborFinderConnector happy
	neighborNode.markAsMaintenance()
	defer neighborNode.unmarkAsMaintenance()

	dummyEntrypoint := uint64(0)
	if err := h.reconnectNeighboursOf(ctx, neighborNode, dummyEntrypoint, neighborVec, compressorDistancer,
		neighborLevel, currentMaximumLayer, deleteList, processedIDs); err != nil {
		return false, errors.Wrap(err, "find and connect neighbors")
	}

	h.metrics.CleanedUp()
	return true, nil
}

View on GitHub (pinned to 75aa4b6d11)

Solutions

  1. Unwrap the error to see the underlying store failure and address it (disk, segment corruption, closed store)
  2. Retry cleanup — tombstoned nodes are re-attempted on later cleanup passes
  3. Check shard/segment integrity; restore from backup if segments are corrupted
  4. Ensure the shard is not being dropped or the store closed concurrently with cleanup
  5. If vectors are persistently unreadable for specific IDs, delete and re-insert those objects
Defensive patterns

Strategy: type-guard

Validate before calling

// Verify neighbor object exists and is readable before reassignment
vec, err := h.store.GetObject(ctx, neighborID)
if err != nil { return fmt.Errorf("neighbor %d unreadable: %w", neighborID, err) }

Type guard

var e storobj.ErrNotFound
if errors.As(err, &e) {
    h.handleDeletedNode(e.DocID, "reassignNeighbor")
    return true, nil // recoverable
}

Try / catch

vec, err := h.vectorByIndexNode(ctx, node)
if err != nil {
    var e storobj.ErrNotFound
    if errors.As(err, &e) { h.handleDeletedNode(e.DocID, "reassignNeighbor"); return true, nil }
    return false, fmt.Errorf("get neighbor vec: %w", err)
}

Prevention

When it happens

Trigger: During tombstone cleanup, reassignNeighbor reads the neighbor's vector via the store; the read returns a non-ErrNotFound error (I/O failure, store closed/corrupted segment, deserialization failure). ErrNotFound is handled separately (the neighbor is treated as deleted).

Common situations: Disk I/O errors or corrupted LSM segments on the shard; a race where the shard is being dropped/closed while cleanup runs; store-level failures after an unclean shutdown.

Related errors


AI-assisted analysis of weaviate/weaviate@75aa4b6d11 (2026-09-04). Data as JSON: /api/errors/1c9174456a5a398d. Report an issue: GitHub.