ruvnet/ruflo · error · Error

Embedding must be Float32Array of length ${this.dimension}

Error message

Embedding must be Float32Array of length ${this.dimension}

What it means

Inside addIntentWithEmbeddings, every element of the embeddings array is checked with `emb instanceof Float32Array && emb.length === this.dimension`. A plain number[], a Float64Array, or a Float32Array of the wrong length all throw, naming the expected dimension. The loop throws on the first bad element, so subsequent embeddings are not validated.

Source

Thrown at v3/@claude-flow/cli/src/ruvector/semantic-router.ts:62

    this.metric = config.metric ?? 'cosine';
  }

  /**
   * Add an intent with pre-computed embeddings
   */
  addIntentWithEmbeddings(
    name: string,
    embeddings: Float32Array[],
    metadata: Record<string, unknown> = {}
  ): void {
    if (!name || !Array.isArray(embeddings)) {
      throw new Error('Must provide name and embeddings array');
    }

    // Validate embeddings
    for (const emb of embeddings) {
      if (!(emb instanceof Float32Array) || emb.length !== this.dimension) {
        throw new Error(`Embedding must be Float32Array of length ${this.dimension}`);
      }
    }

    // Normalize embeddings for cosine similarity
    const normalizedEmbeddings = embeddings.map(emb => this.normalize(emb));

    this.intents.set(name, {
      name,
      embeddings: normalizedEmbeddings,
      metadata,
    });
    this.totalVectors += embeddings.length;
  }

  /**
   * Route a query using a pre-computed embedding
   */
  routeWithEmbedding(embedding: Float32Array, k = 5): RouteResult[] {

View on GitHub (pinned to 6b01dc5a68)

Solutions

  1. Convert each embedding with `Float32Array.from(emb)` before calling addIntentWithEmbeddings.
  2. Regenerate stored embeddings when you change the embedding model or dimension.
  3. Validate length once at ingestion and reject mismatches early.

Example fix

// before
router.addIntentWithEmbeddings('greet', jsonEmbeddings); // number[] -> throws

// after
const dim = 384;
const typed = jsonEmbeddings
  .filter(e => Array.isArray(e) && e.length === dim)
  .map(e => Float32Array.from(e));
router.addIntentWithEmbeddings('greet', typed);
Defensive patterns

Strategy: validation

Validate before calling

function toFloat32Batch(arr, dim) {
  if (!Array.isArray(arr)) throw new Error('embeddings must be an Array');
  return arr.map((e, i) => {
    if (!(e instanceof Float32Array)) e = Float32Array.from(e);
    if (e.length !== dim) throw new Error(`embedding[${i}] length ${e.length} != ${dim}`);
    return e;
  });
}

Type guard

function isFloat32OfLen(e, dim): e is Float32Array {
  return e instanceof Float32Array && e.length === dim;
}

Prevention

When it happens

Trigger: Passing embeddings as number[] (the common JSON-parsed shape) instead of Float32Array; mixing embedding models of different dimensions in one intent; passing a query embedding stored as Float64Array.

Common situations: Loading embeddings from JSON files (which deserialize to number[]); switching embedder dimension without regenerating stored embeddings; receiving embeddings over IPC/structured-clone that changed the typed-array kind.

Related errors


AI-assisted analysis of ruvnet/ruflo@6b01dc5a68 (2026-08-12). Data as JSON: /api/errors/4e3f98a110f03b73. Report an issue: GitHub.