ruvnet/ruflo · error
Cannot compute centroid of empty set
Error message
Cannot compute centroid of empty set
What it means
HyperbolicSpace.centroid() (hyperbolic.ts:1000) computes the Frechet mean by iterative gradient descent and needs at least one point to define a mean, so an empty array is rejected. A single-element input short-circuits to a copy of that point; two or more points run the iterative loop initialized from the projected Euclidean mean.
Source
Thrown at v3/@claude-flow/plugins/src/integrations/ruvector/hyperbolic.ts:1000
// Use exponential map from a with half the tangent to b
const tangent = this.logMap(a, b);
const halfTangent = scale(tangent, 0.5);
return this.expMap(a, halfTangent);
}
/**
* Computes the Frechet mean (centroid) of multiple points.
*
* Uses iterative gradient descent on the sum of squared distances.
*
* @param points - Array of points
* @param maxIter - Maximum iterations
* @param tol - Convergence tolerance
* @returns Frechet mean
*/
centroid(points: number[][], maxIter: number = 100, tol: number = 1e-8): number[] {
if (points.length === 0) {
throw new Error('Cannot compute centroid of empty set');
}
if (points.length === 1) {
return [...points[0]];
}
// Initialize with Euclidean mean, projected onto manifold
let mean = zeros(points[0].length);
for (const p of points) {
mean = add(mean, p);
}
mean = this.projectToManifold(scale(mean, 1 / points.length));
// Iterative refinement
for (let iter = 0; iter < maxIter; iter++) {
// Compute sum of log maps
let gradSum = zeros(points[0].length);
for (const p of points) {
const logP = this.logMap(mean, p);View on GitHub (pinned to fa13ee4ad6)
Solutions
- Skip empty groups before calling centroid: if (group.length === 0) continue
- Return a defined fallback point (e.g. origin or the space's default embedding) for empty sets when your algorithm permits
- Log which group was empty to trace the upstream filter that produced it
Example fix
// before const center = space.centroid(group.embeddings); // throws when group has 0 embeddings // after const center = group.embeddings.length > 0 ? space.centroid(group.embeddings) : space.projectToManifold(new Array(dim).fill(0));
Defensive patterns
Strategy: validation
Validate before calling
function centroidOr(space: HyperbolicSpace, points: number[][], fallback: number[]): number[] {
return points.length > 0 ? space.centroid(points) : fallback;
}
const center = centroidOr(space, groupPoints, space.projectToManifold(new Array(dim).fill(0))); Type guard
function isNonEmptyPoints(v: number[][]): v is [number[], ...number[][]] {
return Array.isArray(v) && v.length > 0 && v.every(p => Array.isArray(p) && p.length > 0);
} Try / catch
try {
mean = space.centroid(points);
} catch (err) {
if (err instanceof Error && err.message === 'Cannot compute centroid of empty set') {
mean = space.projectToManifold(new Array(dim).fill(0)); // neutral fallback
} else throw err;
} Prevention
- Filter or skip empty groups before computing Frechet means in clustered pipelines
- Log empty-group occurrences to catch upstream data gaps early
- Define an explicit fallback point (projected origin) for degenerate cases
When it happens
Trigger: centroid([]) called on results of a filter/map that yielded nothing (e.g. clustering a neighborhood with no members); batching points by group where some groups are empty; dependency-graph code computing hyperbolic centroids of empty relation sets.
Common situations: Graph analytics where a node has zero neighbors; partitioned datasets with empty partitions; upstream data-quality gaps producing zero embeddings for a category.
Related errors
- Cannot calibrate with empty samples
- localCompute: no adapter for graphId=${input.graphId}
- Invalid completion type
- Router multimodal is enabled but LLM_ROUTER_MULTIMODAL_MODEL
- Routes config must be a flat array of routes
AI-assisted analysis of ruvnet/ruflo@fa13ee4ad6 (2026-08-18).
Data as JSON: /api/errors/b61bc9d6b1506068.
Report an issue: GitHub.