ruvnet/ruflo · error · Error

tuneDistillation: empty grid — supply at least one value…

Error message

tuneDistillation: empty grid — supply at least one value per grid axis

What it means

After substituting defaults for every grid axis, the cartesian-product loop would produce zero candidate configs — i.e. the caller supplied only empty arrays for the grid axes. The harness refuses to run a grid search with no points to evaluate.

Solutions

  1. Provide at least one candidate value for every grid axis
  2. Remove axes that have no values from the grid definition

Example fix

Provide at least one value for every grid axis in the tuning configuration; empty axes produce an empty candidate grid.
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at v3/@claude-flow/cli/src/services/distill-tuning.ts:235 when the library encounters an invalid state.

Common situations: See trigger scenarios.


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

Appendix: source

Thrown at v3/@claude-flow/cli/src/services/distill-tuning.ts:235

  if (!Database) {
    throw new Error('tuneDistillation: better-sqlite3 unavailable — cannot run the tuning harness');
  }

  const sourceChecksumBefore = sha256File(dbPath);

  const batchSizes = grid.batchSize ?? DEFAULT_GRID_BATCH_SIZE;
  const dedupDistances = grid.dedupDistance ?? DEFAULT_GRID_DEDUP_DISTANCE;
  const promoteThresholds = grid.promoteThreshold ?? DEFAULT_GRID_PROMOTE_THRESHOLD;
  const configs: TuningConfig[] = [];
  for (const batchSize of batchSizes) {
    for (const dedupDistance of dedupDistances) {
      for (const promoteThreshold of promoteThresholds) {
        configs.push({ batchSize, dedupDistance, promoteThreshold });
      }
    }
  }
  if (configs.length === 0) {
    throw new Error('tuneDistillation: empty grid — supply at least one value per grid axis');
  }

  // ── Splits + query sets: a dedicated read-only copy, never the source itself ──
  const readCopy = copyToTemp(dbPath, tmpDir, 'split-read');
  let outerSplit: TimeSplit;
  let innerSplit: TimeSplit;
  let trainQuerySet: QueryEntry[];
  let heldOutQuerySet: QueryEntry[];
  let heldOutBaselineIndex: PatternIndexEntry[];
  try {
    const readDb = new Database(readCopy, { readonly: true });
    try {
      outerSplit = computeTimeSplit(readDb, trainFraction);
      assertDisjoint(outerSplit.trainRowids, outerSplit.heldOutRowids);

      innerSplit = computeTimeSplit(readDb, trainFraction, {
        extraWhere: `rowid <= ${outerSplit.trainBoundaryRowid}`,
      });

View on GitHub (pinned to fa13ee4ad6)