ruvnet/ruflo · error
ProductQuantizer must be trained before decoding
Error message
ProductQuantizer must be trained before decoding
What it means
Thrown by ProductQuantizer.decode() when the quantizer's isTrained flag is false. Decoding PQ codes requires learned codebooks (this.codebooks[m].centroids); without training they are undefined, so decode() would either crash on undefined centroid access or return garbage. The library refuses to decode rather than emit corrupt reconstructed vectors.
Source
Thrown at v3/@claude-flow/plugins/src/integrations/ruvector/quantization.ts:900
});
}
/**
* Implements IQuantizer interface - encodes vectors.
*/
quantize(vectors: number[][]): Uint8Array[] {
return this.encode(vectors);
}
/**
* Decodes PQ codes back to approximate vectors.
*
* @param codes - PQ codes
* @returns Reconstructed vectors
*/
decode(codes: Uint8Array[]): number[][] {
if (!this.isTrained) {
throw new Error('ProductQuantizer must be trained before decoding');
}
return codes.map((code) => {
const vec = new Array(this.dimensions);
for (let m = 0; m < this.numSubvectors; m++) {
const centroid = this.codebooks[m].centroids[code[m]];
const start = m * this.subvectorDim;
for (let d = 0; d < this.subvectorDim; d++) {
vec[start + d] = centroid[d];
}
}
return vec;
});
}
/**View on GitHub (pinned to fa13ee4ad6)
Solutions
- Call pq.train(trainingVectors) on the same instance before decode()
- If using pretrained artifacts, load them via setCodebooks() or deserializeQuantizer() (both set isTrained) before decoding
- Guard the call: only invoke decode() when the trained getter returns true
- Persist quantizer state with serializeQuantizer after training and restore it in every process that decodes
Example fix
// before
const pq = new ProductQuantizer({ dimensions: 128, numSubvectors: 8 });
const vecs = pq.decode(codes); // throws
// after
const pq = new ProductQuantizer({ dimensions: 128, numSubvectors: 8 });
pq.train(trainingVectors);
const vecs = pq.decode(codes); Defensive patterns
Strategy: validation
Validate before calling
if (!pq.trained) {
pq.train(trainingVectors);
}
const vectors = pq.decode(codes); Type guard
const isTrainedQuantizer = (q: IQuantizer): q is ProductQuantizer => q instanceof ProductQuantizer && q.trained;
Try / catch
try {
const vectors = pq.decode(codes);
} catch (err) {
if (err instanceof Error && err.message.includes('must be trained')) {
pq.train(trainingVectors); // or load persisted codebooks
} else {
throw err;
}
} Prevention
- Treat train() (or deserializeQuantizer) as part of construction: wrap quantizer creation in a factory that always returns a trained instance
- Persist artifacts with serializeQuantizer and load them at startup in every process that decodes
- Add a unit test asserting decode throws before train and succeeds after
When it happens
Trigger: Constructing a ProductQuantizer and calling decode(codes) before calling train(trainingVectors). Also calling decode on a fresh instance after a failed/partial deserializeQuantizer that never reached setCodebooks (which sets isTrained = true).
Common situations: Test code that quantizes with a shared helper but decodes with a newly constructed quantizer; splitting the training and query phases across processes and forgetting to load the persisted codebooks in the query process; assuming the constructor or quantize() trains implicitly.
Related errors
- ProductQuantizer must be trained before computing distances
- Cannot calibrate with empty samples
- Cannot learn thresholds from empty samples
- Dimensions (${options.dimensions}) must be divisible by numS
- Need at least ${this.numCentroids} training vectors, got ${v
AI-assisted analysis of ruvnet/ruflo@fa13ee4ad6 (2026-08-18).
Data as JSON: /api/errors/e96cb1e9831cdc87.
Report an issue: GitHub.