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
- Convert each embedding with `Float32Array.from(emb)` before calling addIntentWithEmbeddings.
- Regenerate stored embeddings when you change the embedding model or dimension.
- 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
- Always coerce stored/JSON embeddings with Float32Array.from at ingestion.
- Regenerate embeddings when changing the embedder or dimension.
- Keep one dimension per router instance; namespace by model if you mix models.
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
- Invalid embedding model name: ${embeddingModel}
- Invalid embedding value at index ${i}: expected finite numbe
- SemanticRouter requires a dimension in config
- Must provide name and embeddings array
- Vector dimension mismatch: ${a.length} vs ${b.length}
AI-assisted analysis of ruvnet/ruflo@6b01dc5a68 (2026-08-12).
Data as JSON: /api/errors/4e3f98a110f03b73.
Report an issue: GitHub.