{"record":{"id":"4e3f98a110f03b73","repo":"ruvnet/ruflo","slug":"embedding-must-be-float32array-of-length-this-di","errorCode":null,"errorMessage":"Embedding must be Float32Array of length ${this.dimension}","messagePattern":"Embedding must be Float32Array of length (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"v3/@claude-flow/cli/src/ruvector/semantic-router.ts","lineNumber":62,"sourceCode":"    this.metric = config.metric ?? 'cosine';\n  }\n\n  /**\n   * Add an intent with pre-computed embeddings\n   */\n  addIntentWithEmbeddings(\n    name: string,\n    embeddings: Float32Array[],\n    metadata: Record<string, unknown> = {}\n  ): void {\n    if (!name || !Array.isArray(embeddings)) {\n      throw new Error('Must provide name and embeddings array');\n    }\n\n    // Validate embeddings\n    for (const emb of embeddings) {\n      if (!(emb instanceof Float32Array) || emb.length !== this.dimension) {\n        throw new Error(`Embedding must be Float32Array of length ${this.dimension}`);\n      }\n    }\n\n    // Normalize embeddings for cosine similarity\n    const normalizedEmbeddings = embeddings.map(emb => this.normalize(emb));\n\n    this.intents.set(name, {\n      name,\n      embeddings: normalizedEmbeddings,\n      metadata,\n    });\n    this.totalVectors += embeddings.length;\n  }\n\n  /**\n   * Route a query using a pre-computed embedding\n   */\n  routeWithEmbedding(embedding: Float32Array, k = 5): RouteResult[] {","sourceCodeStart":44,"sourceCodeEnd":80,"githubUrl":"https://github.com/ruvnet/ruflo/blob/6b01dc5a687b26b3e218f796de45ec51f8fa9e8c/v3/@claude-flow/cli/src/ruvector/semantic-router.ts#L44-L80","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nrouter.addIntentWithEmbeddings('greet', jsonEmbeddings); // number[] -> throws\n\n// after\nconst dim = 384;\nconst typed = jsonEmbeddings\n  .filter(e => Array.isArray(e) && e.length === dim)\n  .map(e => Float32Array.from(e));\nrouter.addIntentWithEmbeddings('greet', typed);","handlingStrategy":"validation","validationCode":"function toFloat32Batch(arr, dim) {\n  if (!Array.isArray(arr)) throw new Error('embeddings must be an Array');\n  return arr.map((e, i) => {\n    if (!(e instanceof Float32Array)) e = Float32Array.from(e);\n    if (e.length !== dim) throw new Error(`embedding[${i}] length ${e.length} != ${dim}`);\n    return e;\n  });\n}","typeGuard":"function isFloat32OfLen(e, dim): e is Float32Array {\n  return e instanceof Float32Array && e.length === dim;\n}","tryCatchPattern":null,"preventionTips":["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."],"tags":["validation","embeddings","typed-array","semantic-router"],"backgroundTag":null,"analyzedSha":"6b01dc5a687b26b3e218f796de45ec51f8fa9e8c","analyzedAt":"2026-08-12T13:20:50.148Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}