{"record":{"id":"19322f319085db44","repo":"ruvnet/ruflo","slug":"cannot-learn-thresholds-from-empty-samples","errorCode":null,"errorMessage":"Cannot learn thresholds from empty samples","messagePattern":"Cannot learn thresholds from empty samples","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"v3/@claude-flow/plugins/src/integrations/ruvector/quantization.ts","lineNumber":500,"sourceCode":"  private readonly bytesPerVector: number;\n\n  constructor(options: BinaryQuantizationOptions) {\n    this.dimensions = options.dimensions;\n    this.threshold = options.threshold ?? 0;\n    this.learnedThresholds = options.learnedThresholds ?? null;\n\n    // Calculate bytes needed (ceil(dimensions / 8))\n    this.bytesPerVector = Math.ceil(this.dimensions / 8);\n  }\n\n  /**\n   * Learns optimal thresholds per dimension from training data.\n   *\n   * @param samples - Training vectors\n   */\n  learnThresholds(samples: number[][]): void {\n    if (samples.length === 0) {\n      throw new Error('Cannot learn thresholds from empty samples');\n    }\n\n    // Compute median per dimension as threshold\n    this.learnedThresholds = new Array(this.dimensions);\n\n    for (let d = 0; d < this.dimensions; d++) {\n      const values = samples.map(s => s[d]).sort((a, b) => a - b);\n      const mid = Math.floor(values.length / 2);\n      this.learnedThresholds[d] = values.length % 2 === 0\n        ? (values[mid - 1] + values[mid]) / 2\n        : values[mid];\n    }\n  }\n\n  /**\n   * Quantizes float32 vectors to binary.\n   *\n   * @param vectors - Input vectors","sourceCodeStart":482,"sourceCodeEnd":518,"githubUrl":"https://github.com/ruvnet/ruflo/blob/fa13ee4ad60ac2090b1480656eb233521790d640/v3/@claude-flow/plugins/src/integrations/ruvector/quantization.ts#L482-L518","documentation":"BinaryQuantizer.learnThresholds() (quantization.ts:500) computes a per-dimension median threshold from training vectors to decide the 0/1 bit each dimension encodes. Median computation requires at least one value per dimension, so an empty samples array throws. The quantizer otherwise falls back to zero thresholds.","triggerScenarios":"learnThresholds([]) when the training fetch returned no rows; slicing a dataset with .slice(0, 0) or an empty feature group; test fixtures that forgot to include vectors.","commonSituations":"First-run pipelines before any data exists; ETL filters (tenant, date range) producing empty result sets; unit tests with stubbed empty datasets.","solutions":["Guard the call: only invoke learnThresholds when samples.length > 0","Fall back to the default zero thresholds (skip learning) when data is missing","Fail the job earlier with a clear message if training data is a hard requirement"],"exampleFix":"// before\nbq.learnThresholds(trainSet); // throws if trainSet is []\n\n// after\nif (trainSet.length > 0) {\n  bq.learnThresholds(trainSet);\n} else {\n  bq.learnThresholds([new Array(bq.dimensions).fill(0)]); // neutral threshold until data arrives\n}","handlingStrategy":"validation","validationCode":"if (samples.length === 0) {\n  throw new Error('learnThresholds requires at least one training vector');\n}\nbq.learnThresholds(samples);","typeGuard":"function isNonEmptySamples(v: number[][]): v is [number[], ...number[][]] {\n  return Array.isArray(v) && v.length > 0;\n}","tryCatchPattern":"try {\n  bq.learnThresholds(samples);\n} catch (err) {\n  if (err instanceof Error && err.message === 'Cannot learn thresholds from empty samples') {\n    bq.learnThresholds([new Array(dim).fill(0)]); // neutral thresholds until real data\n  } else throw err;\n}","preventionTips":["Validate training-set size before threshold learning","Make empty ETL results loud (log/abort) instead of flowing into quantizer training","Include non-empty vector fixtures in unit tests for the binary quantizer"],"tags":["quantization","binary-quantization","training-data","empty-input"],"backgroundTag":"empty-training-data","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"}