ruvnet/ruflo · error · Error

Hard negative miner not initialized

Error message

Hard negative miner not initialized

What it means

Thrown by mineHardNegatives() when hardMiner is null. This is the most fragile of the attention features: initializeTraining() constructs HardNegativeMiner(5, 'semi_hard') inside its own try/catch, so hardMiner stays null both when the whole @ruvector/attention package is missing AND when the package exists but lacks HardNegativeMiner or its constructor throws (older/incompatible version) — init continues either way, listing 'Hard Negative Mining' in features only on success.

Source

Thrown at v3/@claude-flow/cli/src/services/ruvector-training.ts:678

 * Get curriculum difficulty for current step
 */
export function getCurriculumDifficulty(step: number): number {
  if (!curriculum) {
    return 1.0; // Full difficulty if no curriculum
  }

  return curriculum.getDifficulty(step);
}

/**
 * Mine hard negatives for better training
 */
export function mineHardNegatives(
  anchor: Float32Array,
  candidates: Float32Array[]
): number[] {
  if (!hardMiner) {
    throw new Error('Hard negative miner not initialized');
  }

  return hardMiner.mine(anchor, candidates);
}

/**
 * Benchmark the training system
 */
export async function benchmarkTraining(
  dim?: number,
  iterations?: number
): Promise<BenchmarkResult[]> {
  const attention: any = await importWithInterop('@ruvector/attention');
  lastBenchmark = attention.benchmarkAttention(dim || 256, 100, iterations || 1000);
  return lastBenchmark ?? [];
}

// ============================================

View on GitHub (pinned to fa13ee4ad6)

Solutions

  1. Await initializeTraining() and assert features includes 'Hard Negative Mining' — this is the only reliable signal, since construction failures are swallowed.
  2. Pin a @ruvector/attention version whose HardNegativeMiner(5, 'semi_hard') constructor matches this API.
  3. If mining stays unavailable, fall back to random or hardest-negative selection implemented locally.
  4. Re-initialize after cleanup().

Example fix

// before
const idxs = mineHardNegatives(anchor, candidates); // throws if miner silently absent

// after
const init = await initializeTraining();
const canMine = init.features.includes('Hard Negative Mining');
const idxs = canMine
  ? mineHardNegatives(anchor, candidates)
  : pickRandomNegatives(candidates, 5); // local fallback
Defensive patterns

Strategy: validation

Validate before calling

const init = await initializeTraining();
const canMine = init.features.includes('Hard Negative Mining'); // only reliable signal — constructor failures are swallowed
const idxs = canMine
  ? mineHardNegatives(anchor, candidates)
  : pickRandomNegatives(candidates, 5); // local fallback

Type guard

async function miningReady(): Promise<boolean> {
  const init = await initializeTraining();
  return init.features.includes('Hard Negative Mining');
}

Try / catch

try {
  return mineHardNegatives(anchor, candidates);
} catch (e) {
  if (e instanceof Error && e.message === 'Hard negative miner not initialized') {
    return pickRandomNegatives(candidates, 5); // degrade to random negatives
  }
  throw e;
}

Prevention

When it happens

Trigger: Init without @ruvector/attention installed; a version of @ruvector/attention that predates or renames HardNegativeMiner (constructor throws, swallowed silently); mining called before init or after cleanup().

Common situations: Version skew after upgrading the attention package (API changed, mining silently dropped); optional-dep pruning in production installs; relying on mining without checking the features array because flash attention worked fine.

Related errors


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