ruvnet/ruflo · error · Error

scoreBy='nearest' requires a probe vector

Error message

scoreBy='nearest' requires a probe vector

What it means

Thrown by the agenticow_speculate MCP tool when scoreBy resolves to 'nearest' (the default) but no probe vector was supplied. Scoring by 'nearest' ranks each speculative branch by how close its best-ingested vector sits to the probe, so the probe is mandatory input for that mode. Without it the similarity score is undefined and the tool refuses to guess.

Source

Thrown at v3/@claude-flow/cli/src/mcp-tools/agenticow-speculate-tools.ts:149

      },
      required: ['basePath', 'candidates'],
    },
    handler: async (input) => {
      const api = await loadAgenticow();
      if (!api) return degradedResult('agenticow-not-found');

      const basePath = resolveMemoryPath(String(input.basePath));
      const dimension = input.dimension as number | undefined;
      const scoreBy = (input.scoreBy as string) === 'count' ? 'count' : 'nearest';
      const k = Number.isInteger(input.k) && (input.k as number) > 0 ? (input.k as number) : 1;
      const probe = Array.isArray(input.probe) ? (input.probe as number[]) : null;

      const rawCandidates = input.candidates as CandidateInput[];
      if (!Array.isArray(rawCandidates) || rawCandidates.length === 0) {
        throw new Error('at least one candidate is required');
      }
      if (scoreBy === 'nearest' && !probe) {
        throw new Error("scoreBy='nearest' requires a probe vector");
      }

      // Build the generic {label, fn} candidates. Each fn ingests into its own
      // branch handle, then (for 'nearest') probes it so we can score.
      // Map validated label → explicit branchPath so the branchPath() resolver
      // below is O(1) instead of re-scanning + re-validating rawCandidates per
      // candidate (explore() calls branchPath once per candidate → was O(n²)).
      const explicitBranchPaths = new Map<string, string>();
      const candidates: SpeculativeCandidate<CandidateOutcome>[] = rawCandidates.map((c) => {
        const label = validateLabel(String(c.label));
        if (!Array.isArray(c.ingest) || c.ingest.length === 0) {
          throw new Error(`candidate ${label} must ingest at least one vector`);
        }
        if (typeof c.branchPath === 'string' && c.branchPath) {
          explicitBranchPaths.set(label, c.branchPath);
        }
        const records = c.ingest.map((r) => ({
          ...(Number.isInteger(r.id) ? { id: r.id as number } : {}),

View on GitHub (pinned to 6b01dc5a68)

Solutions

  1. Supply a numeric probe array whose length equals the candidate vector dimension, e.g. probe: [0.12, -0.03, ...].
  2. If you only want to rank branches by how many ingests they accepted, set scoreBy: 'count' instead and omit probe.
  3. Verify probe is a JS/JSON array of numbers, not a stringified array or object — a non-array is treated as missing.
  4. Confirm the probe dimension matches each candidate's ingest vectors or the branch query will fail downstream.

Example fix

// before
agenticow_speculate({ basePath, candidates, scoreBy: 'nearest' })
// after
agenticow_speculate({ basePath, candidates, scoreBy: 'nearest', probe: embedding })
Defensive patterns

Strategy: validation

Validate before calling

function validateSpeculateInput(input) {
  const scoreBy = input.scoreBy === 'count' ? 'count' : 'nearest';
  if (scoreBy === 'nearest') {
    if (!Array.isArray(input.probe) || input.probe.length === 0) {
      throw new Error("scoreBy='nearest' requires a non-empty probe array");
    }
    if (!input.probe.every((n) => typeof n === 'number' && Number.isFinite(n))) {
      throw new Error('probe must be an array of finite numbers');
    }
  }
}

Type guard

function isProbeVector(v: unknown): v is number[] {
  return Array.isArray(v) && v.length > 0 && v.every((n) => typeof n === 'number' && Number.isFinite(n));
}

Prevention

When it happens

Trigger: Calling agenticow_speculate with scoreBy omitted (defaults to 'nearest') or explicitly set to 'nearest', while omitting the probe field. Also triggers when probe is passed as a non-array (e.g. a string or object) because the handler nulls it via `Array.isArray(input.probe) ? ... : null`.

Common situations: A caller copies a 'count'-mode example and switches scoreBy back to 'nearest' without adding a probe; passing probe as a JSON string instead of a numeric array; migrating from a scoreBy='count' workflow to similarity ranking and forgetting the query embedding.

Related errors


AI-assisted analysis of ruvnet/ruflo@6b01dc5a68 (2026-08-12). Data as JSON: /api/errors/92395237964775f3. Report an issue: GitHub.