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
- Provide at least one candidate value for every grid axis
- 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)