ruvnet/ruflo · error
selfConsistency: N must be a positive integer, got ${config.
Error message
selfConsistency: N must be a positive integer, got ${config.N} What it means
selfConsistency() validates its sample count up front: config.N must be a positive integer (Number.isInteger true and > 0). Zero, negatives, fractional values like 2.5, NaN, and Infinity all fail before the operation is run even once, so no samples are wasted.
Source
Thrown at v3/@claude-flow/neural/src/utils/self-consistency.ts:69
* For 'majority': fraction of samples matching finalAnswer (0..1).
* For 'mean': 1 - normalized stddev (rough confidence proxy).
* For 'first': always 1.
*/
agreement: number;
/** The config used for this run. */
config: SelfConsistencyConfig;
}
/**
* Run an operation N times and aggregate. The operation is awaited
* sequentially — if the caller wants concurrency they can wrap it themselves.
*/
export async function selfConsistency<T>(
operation: () => Promise<T> | T,
config: SelfConsistencyConfig,
): Promise<SelfConsistencyResult<T>> {
if (!Number.isInteger(config.N) || config.N <= 0) {
throw new Error(`selfConsistency: N must be a positive integer, got ${config.N}`);
}
const samples: T[] = [];
for (let i = 0; i < config.N; i++) {
samples.push(await operation());
}
const aggregator: SelfConsistencyAggregator = config.aggregator ?? 'majority';
let finalAnswer: T;
let agreement: number;
if (aggregator === 'majority') {
// Group by JSON-stringified value (handles primitives, plain objects,
// arrays). Float32Array does NOT JSON-encode losslessly by default —
// callers wanting f32 majority should pre-convert via Array.from.
const counts = new Map<string, { value: T; count: number }>();
for (const s of samples) {View on GitHub (pinned to fa13ee4ad6)
Solutions
- Default N explicitly at the call site: config.N ?? 3
- Coerce computed values with Math.max(1, Math.round(n)) before building the config
- Validate any user-supplied N (CLI arg, env var, API field) before it reaches selfConsistency
- Fail fast in your own config loader with a clear message instead of letting the library reject it later
Example fix
// before
await selfConsistency(op, { N: ratio * 10, aggregator: 'mean' });
// after
const N = Math.max(1, Math.round(ratio * 10));
await selfConsistency(op, { N, aggregator: 'mean' }); Defensive patterns
Strategy: validation
Validate before calling
const N = Number.isInteger(cfg.N) && (cfg.N as number) > 0 ? cfg.N : 3;
await selfConsistency(op, { ...cfg, N }); Type guard
function isPositiveInteger(n: unknown): n is number {
return typeof n === 'number' && Number.isInteger(n) && n > 0;
} Prevention
- Always set an explicit N default at the call site
- Round and clamp computed counts: Math.max(1, Math.round(n))
- Validate CLI/env-sourced counts in your config loader before use
- Unit-test the config builder with missing inputs
When it happens
Trigger: Passing N: 0 because a config default was never set; computing N from a ratio that yields a float (e.g. 3 * 0.5); NaN from Number.parseInt(undefined) on a missing CLI/env flag; a negative result from a subtraction like budget - used.
Common situations: CLI- or env-driven sampling counts where a missing flag coerces to 0 or NaN; dynamic N = Math.round(quality * k) with quality 0; configs copied between callers with different N semantics.
Understand the failure class
Background: "must be a positive integer", "cannot be empty", "invalid argument": how invalid-argument errors work across open-source libraries — this error's family across 33 libraries.
Related errors
- anchorPath and anchorHash must be supplied together
- Temperature must be between 0 and 2
- localCompute: no adapter for graphId=${input.graphId}
- Invalid completion type
- Router multimodal is enabled but LLM_ROUTER_MULTIMODAL_MODEL
AI-assisted analysis of ruvnet/ruflo@fa13ee4ad6 (2026-08-18).
Data as JSON: /api/errors/cbc0b6a5abbbdf09.
Report an issue: GitHub.