weaviate/weaviate · error

find and connect neighbors

Error message

find and connect neighbors

What it means

Wrapped failure from reconnectNeighboursOf while re-linking a neighbor after a tombstoned node was removed from the HNSW graph. reassignNeighbor finds the affected neighbor, retrieves its vector, and asks the neighbor finder/connector to discover and connect new neighbors; any failure in that 'find and connect' step is wrapped with this message and aborts this node's reassignment for the current cleanup cycle.

Source

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

		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
}

func connectionsPointTo(connections *packedconn.Connections, needles helpers.AllowList) bool {
	// Use CopyLayer with buffer reuse to avoid allocations per layer
	buffer := make([]uint64, 0, 64)

	for layer := uint8(0); layer < connections.Layers(); layer++ {
		buffer = connections.CopyLayer(buffer, layer)
		for _, pointer := range buffer {
			if needles.Contains(pointer) {
				return true
			}
		}
	}

View on GitHub (pinned to 75aa4b6d11)

Solutions

  1. Unwrap to find the root cause; if it is ErrVectorLength, locate objects with wrong-dimension vectors and re-insert them with correct dimensions
  2. Retry — cleanup is periodic and will retry failed reassignments
  3. Check that the collection's vectorizer dimension matches all stored vectors
  4. Ensure the process is not being shut down mid-cleanup (context cancellation); give cleanup time on a healthy node
  5. If the graph remains inconsistent, trigger a full index rebuild
Defensive patterns

Strategy: try-catch

Validate before calling

// Pre-validate vector dimensions for the neighbor before reconnect
if len(neighborVec) != h.dim() {
    return fmt.Errorf("neighbor vec dim %d != index dim %d", len(neighborVec), h.dim())
}

Type guard

var vecErr distancer.ErrVectorLength
if errors.As(err, &vecErr) { /* dimension mismatch: fix data, not the graph */ }

Try / catch

err := h.reconnectNeighboursOf(ctx, node, dummy, vec, d, level, maxLayer, deleteList, processed)
if err != nil {
    if errors.Is(err, distancer.ErrVectorLength) { /* flag object for re-insert */ }
    return false, fmt.Errorf("find and connect neighbors: %w", err)
}

Prevention

When it happens

Trigger: Tombstone cleanup calls reassignNeighbor; reconnectNeighboursOf fails — commonly due to a length-mismatch (ErrVectorLength) when comparing the neighbor's vector against candidates, store read failures while loading candidate nodes, or context cancellation.

Common situations: Mixed-dimension vectors in one collection after a schema/vectorizer change; heavy concurrent writes interfering with cleanup; context cancelled due to shutdown or timeout during a long cleanup pass.

Related errors


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