ruvnet/ruflo · error · Error
tuneDistillation: better-sqlite3 unavailable — cannot run th
Error message
tuneDistillation: better-sqlite3 unavailable — cannot run the tuning harness
What it means
tuneDistillation needs better-sqlite3 to open read-only copies and run the candidate harness; loadBetterSqlite3() returns null when the native module cannot be loaded. Because tuning requires real sqlite I/O, an absent native binding is unrecoverable for this function (unlike the sql.js WASM path used elsewhere for persistence).
Source
Thrown at v3/@claude-flow/cli/src/services/distill-tuning.ts:218
const {
dbPath,
grid = {},
namespaces,
trainFraction = DEFAULT_TRAIN_FRACTION,
queryNamespaces = DEFAULT_QUERY_NAMESPACES,
topK = DEFAULT_TOP_K,
now,
tmpDir = os.tmpdir(),
verbose = false,
} = options;
if (!dbPath || !fs.existsSync(dbPath)) {
throw new Error(`tuneDistillation: source db not found at ${dbPath}`);
}
const Database = await loadBetterSqlite3();
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');
}View on GitHub (pinned to 6b01dc5a68)
Solutions
- Install/rebuild the native module: npm install better-sqlite3 (or npm rebuild better-sqlite3).
- Ensure build tools are present on the host (python3, make, g++) so node-gyp can compile when no prebuilt binary matches.
- On Electron, rebuild for the target ABI with electron-rebuild.
- If the platform cannot provide better-sqlite3, do not call tuneDistillation — gate on a capability check first.
Example fix
// before
await tuneDistillation({ dbPath, ... }); // throws 'better-sqlite3 unavailable'
// after — gate the call
const Database = await loadBetterSqlite3();
if (!Database) {
console.warn('better-sqlite3 missing; skipping distillation tuning');
} else {
await tuneDistillation({ dbPath, ... });
} Defensive patterns
Strategy: validation
Validate before calling
const Database = await loadBetterSqlite3();
if (!Database) {
console.warn('better-sqlite3 unavailable; skipping tuneDistillation');
} else {
await tuneDistillation({ dbPath, ... });
} Try / catch
try {
await tuneDistillation({ dbPath, ... });
} catch (e) {
if ((e as Error).message.includes('better-sqlite3 unavailable')) {
// install/rebuild the native module, then retry
} else throw e;
} Prevention
- Install better-sqlite3 with prebuilt or build-tool support (python3, make, g++).
- Rebuild native deps after a Node/Electron major upgrade (npm rebuild better-sqlite3).
- Do not --omit=optional if tuning is required.
- Gate tuning calls behind a loadBetterSqlite3() capability check.
When it happens
Trigger: better-sqlite3 is an optionalDependency that failed to install or load: missing native build tools at npm install, an ABI/arch mismatch (e.g. under a different Node/Electron major), the package was pruned by --omit=optional, or a corrupted prebuilt binary.
Common situations: CI image without build-essential / python where prebuilt binaries are unavailable for the platform; upgrading Node.js major without reinstalling native deps; running inside Electron where the ABI does not match the installed Node binding; Alpine/musl where prebuilt glibc binaries fail.
Related errors
- tuneDistillation: source db not found at ${dbPath}
- tuneDistillation: empty grid — supply at least one value per
- tuneDistillation: every grid candidate was skipped — see can
- tuneDistillation: source DB checksum changed during tuning —
- tuneDistillation: train/held-out partitions are not disjoint
AI-assisted analysis of ruvnet/ruflo@6b01dc5a68 (2026-08-12).
Data as JSON: /api/errors/b21a1aa6c9893e78.
Report an issue: GitHub.