ruvnet/ruflo · error

Dimensions (${options.dimensions}) must be divisible by numS

Error message

Dimensions (${options.dimensions}) must be divisible by numSubvectors (${options.numSubvectors})

What it means

ProductQuantizer's constructor (quantization.ts:694) requires dimensions % numSubvectors === 0 because each subvector codebook covers an equal slice of dimensions (subvectorDim = dimensions / numSubvectors). Any remainder makes slicing ambiguous, so construction fails immediately with both values in the message.

Source

Thrown at v3/@claude-flow/plugins/src/integrations/ruvector/quantization.ts:694

  readonly dimensions: number;
  readonly numSubvectors: number;
  readonly numCentroids: number;
  readonly subvectorDim: number;

  protected codebooks: Codebook[] = [];
  protected isTrained: boolean = false;
  protected readonly maxIterations: number;
  protected readonly tolerance: number;
  protected readonly rng: () => number;

  constructor(options: ProductQuantizationOptions) {
    this.dimensions = options.dimensions;
    this.numSubvectors = options.numSubvectors;
    this.numCentroids = options.numCentroids;

    // Validate dimensions divisibility
    if (options.dimensions % options.numSubvectors !== 0) {
      throw new Error(
        `Dimensions (${options.dimensions}) must be divisible by numSubvectors (${options.numSubvectors})`
      );
    }

    this.subvectorDim = options.dimensions / options.numSubvectors;
    this.maxIterations = options.maxIterations ?? 100;
    this.tolerance = options.tolerance ?? 1e-6;
    this.rng = createRng(options.seed ?? 42);
  }

  /**
   * Trains codebooks from training data using k-means clustering.
   *
   * @param vectors - Training vectors
   */
  async train(vectors: number[][]): Promise<void> {
    if (vectors.length < this.numCentroids) {
      throw new Error(

View on GitHub (pinned to fa13ee4ad6)

Solutions

  1. Pick numSubvectors that divides dimensions exactly (e.g. 1536: 8, 16, 24, 32, 48; 768: 8, 12, 16, 24)
  2. Compute it: const m = largestPowerOfTwoDividing(dimensions) or gcd-based choice
  3. Validate the pair in config loading: assert dimensions % numSubvectors === 0 with both values in the error

Example fix

// before
const pq = new ProductQuantizer({ dimensions: 1536, numSubvectors: 100, numCentroids: 256 }); // throws

// after
const dims = 1536;
const numSubvectors = 16; // 1536 / 16 = 96-dim subvectors
const pq = new ProductQuantizer({ dimensions: dims, numSubvectors, numCentroids: 256 });
Defensive patterns

Strategy: validation

Validate before calling

function assertPQOptions(dimensions: number, numSubvectors: number) {
  if (!Number.isInteger(dimensions) || dimensions <= 0) throw new TypeError(`bad dimensions ${dimensions}`);
  if (!Number.isInteger(numSubvectors) || numSubvectors <= 0) throw new TypeError(`bad numSubvectors ${numSubvectors}`);
  if (dimensions % numSubvectors !== 0) {
    throw new RangeError(`dimensions ${dimensions} not divisible by numSubvectors ${numSubvectors}`);
  }
}
assertPQOptions(cfg.dimensions, cfg.numSubvectors);
const pq = new ProductQuantizer(cfg);

Type guard

function isValidPQConfig(cfg: { dimensions: number; numSubvectors: number }): boolean {
  return cfg.dimensions > 0 && cfg.numSubvectors > 0 && cfg.dimensions % cfg.numSubvectors === 0;
}

Try / catch

try {
  pq = new ProductQuantizer(cfg);
} catch (err) {
  if (err instanceof Error && err.message.includes('must be divisible by numSubvectors')) {
    cfg = { ...cfg, numSubvectors: 8 }; // retry with a standard divisor
    pq = new ProductQuantizer(cfg);
  } else throw err;
}

Prevention

When it happens

Trigger: new ProductQuantizer({ dimensions: 1536, numSubvectors: 100 }) — 1536 % 100 != 0; reusing an 8-subvector config with a 312-dim embedding model; odd dimensions like 127 or 200 with non-divisor M.

Common situations: Switching embedding providers (1536 for ada-002, 768/1024 for others) without adjusting numSubvectors; copying the default M=8 into configs for models with dimensions not divisible by 8; hand-tuned M values that don't factor the dimension.

Related errors


AI-assisted analysis of ruvnet/ruflo@fa13ee4ad6 (2026-08-18). Data as JSON: /api/errors/cff7603544ed2b2e. Report an issue: GitHub.