{"record":{"id":"320b60f858d33efd","repo":"ruvnet/ruflo","slug":"productquantizer-must-be-trained-before-encoding","errorCode":null,"errorMessage":"ProductQuantizer must be trained before encoding","messagePattern":"ProductQuantizer must be trained before encoding","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"v3/@claude-flow/plugins/src/integrations/ruvector/quantization.ts","lineNumber":869,"sourceCode":"      const dist = squaredEuclideanDistance(subvector, centroids[i]);\n      if (dist < minDist) {\n        minDist = dist;\n        minIdx = i;\n      }\n    }\n\n    return minIdx;\n  }\n\n  /**\n   * Encodes vectors to PQ codes.\n   *\n   * @param vectors - Input vectors\n   * @returns PQ codes (one byte per subvector, assuming K=256)\n   */\n  encode(vectors: number[][]): Uint8Array[] {\n    if (!this.isTrained) {\n      throw new Error('ProductQuantizer must be trained before encoding');\n    }\n\n    return vectors.map((vec) => {\n      const codes = new Uint8Array(this.numSubvectors);\n\n      for (let m = 0; m < this.numSubvectors; m++) {\n        const start = m * this.subvectorDim;\n        const subvector = vec.slice(start, start + this.subvectorDim);\n        codes[m] = this.findNearestCentroid(subvector, this.codebooks[m].centroids);\n      }\n\n      return codes;\n    });\n  }\n\n  /**\n   * Implements IQuantizer interface - encodes vectors.\n   */","sourceCodeStart":851,"sourceCodeEnd":887,"githubUrl":"https://github.com/ruvnet/ruflo/blob/fa13ee4ad60ac2090b1480656eb233521790d640/v3/@claude-flow/plugins/src/integrations/ruvector/quantization.ts#L851-L887","documentation":"ProductQuantizer.encode() (quantization.ts:869) maps each subvector to its nearest codebook centroid, which is impossible before train() has built the codebooks. The isTrained flag is protected, set only after successful training, and encode() refuses to run while it is false, throwing this error to prevent encoding against undefined centroids.","triggerScenarios":"Calling encode(vectors) on a freshly constructed ProductQuantizer; train() threw midway (e.g. insufficient data) and the error was swallowed, leaving the quantizer untrained; deserializing a quantizer without restoring codebooks before encoding; separate encode/decode services where the encoder node never ran training.","commonSituations":"Skipping the training step in quick prototypes; orchestration bugs that run the encode stage before the train stage; exceptions from train() caught too broadly so the pipeline continues.","solutions":["Await train(trainingVectors) to completion before any encode() call","Wrap train() so failures abort the pipeline instead of falling through to encode","When restoring from persistence, use the deserialize path that rebuilds codebooks and trained state rather than constructing a new instance","Order pipeline stages explicitly: train -> encode -> store"],"exampleFix":"// before\nconst pq = new ProductQuantizer({ dimensions: 128, numSubvectors: 8, numCentroids: 256 });\nconst codes = pq.encode(vectors); // throws: not trained\n\n// after\nawait pq.train(trainingVectors); // must succeed first\nconst codes = pq.encode(vectors);","handlingStrategy":"try-catch","validationCode":"// isTrained is protected; track training state at the call site.\nlet trained = false;\nawait pq.train(trainingVectors);\ntrained = true;\nif (!trained) throw new Error('Refusing to encode: quantizer not trained');\nconst codes = pq.encode(vectors);","typeGuard":null,"tryCatchPattern":"try {\n  codes = pq.encode(vectors);\n} catch (err) {\n  if (err instanceof Error && err.message === 'ProductQuantizer must be trained before encoding') {\n    await pq.train(trainingVectors); // train once, then retry\n    codes = pq.encode(vectors);\n  } else throw err;\n}","preventionTips":["Always await train() before encode() and abort the pipeline if train() throws","Avoid blanket catch/continue around training steps that masks an untrained state","When restoring quantizers from storage, use the deserialization path that rebuilds codebooks instead of new ProductQuantizer()"],"tags":["quantization","state-machine","training-required","product-quantization"],"backgroundTag":"model-not-trained","analyzedSha":"fa13ee4ad60ac2090b1480656eb233521790d640","analyzedAt":"2026-08-18T21:34:22.708Z","contentChangedAt":"2026-08-18T21:34:22.708Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}