{"record":{"id":"0136094fa26ae81d","repo":"ruvnet/ruflo","slug":"expected-this-numsubvectors-codebooks-got-co","errorCode":null,"errorMessage":"Expected ${this.numSubvectors} codebooks, got ${codebooks.length}","messagePattern":"Expected (.+?) codebooks, got (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"v3/@claude-flow/plugins/src/integrations/ruvector/quantization.ts","lineNumber":1048,"sourceCode":"    return `${ratio.toFixed(1)}x`;\n  }\n\n  /**\n   * Gets the trained codebooks.\n   */\n  getCodebooks(): Codebook[] {\n    return this.codebooks.map(cb => ({\n      centroids: cb.centroids.map(c => [...c]),\n      counts: [...cb.counts],\n    }));\n  }\n\n  /**\n   * Sets codebooks directly (for loading pretrained).\n   */\n  setCodebooks(codebooks: Codebook[]): void {\n    if (codebooks.length !== this.numSubvectors) {\n      throw new Error(`Expected ${this.numSubvectors} codebooks, got ${codebooks.length}`);\n    }\n    this.codebooks = codebooks;\n    this.isTrained = true;\n  }\n\n  /**\n   * Checks if the quantizer is trained.\n   */\n  get trained(): boolean {\n    return this.isTrained;\n  }\n}\n\n// ============================================================================\n// Optimized Product Quantization (OPQ)\n// ============================================================================\n\n/**","sourceCodeStart":1030,"sourceCodeEnd":1066,"githubUrl":"https://github.com/ruvnet/ruflo/blob/fa13ee4ad60ac2090b1480656eb233521790d640/v3/@claude-flow/plugins/src/integrations/ruvector/quantization.ts#L1030-L1066","documentation":"Thrown by ProductQuantizer.setCodebooks() when the supplied array length differs from the quantizer's numSubvectors. Each PQ code byte m indexes codebooks[m], so the codebook count must exactly match M. This is a shape check on pretrained model data and typically means the saved artifact was trained with a different configuration than the current instance.","triggerScenarios":"Deserializing codebooks saved from a quantizer trained with numSubvectors=8 into an instance configured with 16 (or vice versa); changing numSubvectors in options between training and loading; hand-assembling a codebook array with the wrong length.","commonSituations":"Tuning M for memory/speed and reusing an old artifact; loading a shared pretrained model in a service whose config drifted from the training config; forgetting to persist/re-read numSubvectors alongside the codebooks.","solutions":["Construct the ProductQuantizer with the same dimensions and numSubvectors that were used at train time (persist them with the artifact and read them back)","If you intentionally changed M, re-train and re-save the codebooks","Validate codebooks.length === pq.numSubvectors before calling setCodebooks, and fail with a message naming both values"],"exampleFix":"// before\nconst pq = new ProductQuantizer({ dimensions: 128, numSubvectors: 16 });\npq.setCodebooks(saved.codebooks); // saved with M=8 -> throws\n\n// after\nconst pq = new ProductQuantizer({\n  dimensions: saved.dimensions,\n  numSubvectors: saved.numSubvectors,\n});\npq.setCodebooks(saved.codebooks);","handlingStrategy":"validation","validationCode":"if (codebooks.length !== pq.numSubvectors) {\n  throw new Error(\n    `Artifact mismatch: ${codebooks.length} codebooks for M=${pq.numSubvectors}; retrain or fix config`\n  );\n}\npq.setCodebooks(codebooks);","typeGuard":"const isCodebookArrayFor = (cbs: Codebook[], m: number): cbs is Codebook[] =>\n  Array.isArray(cbs) && cbs.length === m && cbs.every(cb =>\n    Array.isArray(cb.centroids) && cb.centroids.length > 0\n  );","tryCatchPattern":"try {\n  pq.setCodebooks(codebooks);\n} catch (err) {\n  if (err instanceof Error && err.message.startsWith('Expected ')) {\n    throw new Error(`Stale PQ artifact (codebook count mismatch): ${err.message}`);\n  }\n  throw err;\n}","preventionTips":["Persist dimensions and numSubvectors inside the artifact and construct the quantizer from them on load","Bump an artifact version field whenever training config changes and refuse to load older versions","Never hardcode numSubvectors at the load site"],"tags":["quantization","config-mismatch","deserialization","validation"],"backgroundTag":"dimension-mismatch","analyzedSha":"fa13ee4ad60ac2090b1480656eb233521790d640","analyzedAt":"2026-08-18T21:34:22.708Z","contentChangedAt":"2026-08-18T21:34:22.708Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}