ruvnet/ruflo · error · RangeError
lambda must be in (0, 1)
Error message
lambda must be in (0, 1)
What it means
Thrown by sequentialEvidenceVerdict() as a RangeError when the e-process betting fraction lambda is not strictly in the open interval (0, 1). Lambda determines the per-discordant-pair multiplier (1+lambda for a candidate win, 1-lambda for a baseline win); at 0 or 1 the martingale property breaks (trivial multiplier or bankruptcy). Default is 0.5 (no tuning needed).
Source
Thrown at v3/@claude-flow/cli/src/services/flywheel-sequential-evidence.ts:97
if (!Number.isInteger(testIndex) || testIndex < 1) throw new RangeError('testIndex must be a positive integer');
if (!(alphaTotal > 0 && alphaTotal < 1)) throw new RangeError('alphaTotal must be in (0, 1)');
return (alphaTotal * 6) / (Math.PI * Math.PI * testIndex * testIndex);
}
/**
* Fold paired outcomes into an anytime-valid e-value and judge it against the
* k-th test's allocated alpha. Deterministic; order of outcomes does not
* change the final e-value (the product commutes).
*/
export function sequentialEvidenceVerdict(
outcomes: PairedTaskOutcome[],
testIndex: number,
config: SequentialEvidenceConfig = {},
): SequentialEvidenceVerdict {
const alphaTotal = config.alphaTotal ?? DEFAULT_ALPHA_TOTAL;
const lambda = config.lambda ?? DEFAULT_LAMBDA;
const epsilon = config.epsilon ?? DEFAULT_SCORE_EPSILON;
if (!(lambda > 0 && lambda < 1)) throw new RangeError('lambda must be in (0, 1)');
const alphaAllocated = alphaForTest(testIndex, alphaTotal);
const threshold = 1 / alphaAllocated;
let eValue = 1;
let informativePairs = 0;
for (const o of outcomes) {
const delta = o.candidateScore - o.baselineScore;
if (Math.abs(delta) <= epsilon) continue; // concordant: no information
informativePairs++;
// Under the null a discordant pair favors either arm with probability 1/2,
// so E[multiplier] = 1 and the running product is a martingale.
eValue *= delta > 0 ? 1 + lambda : 1 - lambda;
}
return {
significant: eValue >= threshold,
eValue,
threshold,View on GitHub (pinned to 6b01dc5a68)
Solutions
- Omit lambda from config to use the 0.5 default.
- Use any value strictly between 0 and 1 (e.g. 0.3, 0.5, 0.8).
- Validate sequentialLambda before invoking the promotion path.
Example fix
// before
sequentialEvidenceVerdict(outcomes, k, { lambda: 1 });
// after
sequentialEvidenceVerdict(outcomes, k); // default lambda = 0.5 Defensive patterns
Strategy: validation
Validate before calling
if (config.lambda !== undefined && !(config.lambda > 0 && config.lambda < 1)) {
throw new RangeError(`lambda must be in (0,1), got ${config.lambda}`);
} Type guard
const isValidLambda = (x: unknown): x is number => typeof x === 'number' && x > 0 && x < 1;
Prevention
- Omit lambda in config to use the 0.5 default (no tuning needed).
- Validate sequentialLambda once at config load and reject early.
- Document that lambda is strictly exclusive of 0 and 1.
When it happens
Trigger: Calling sequentialEvidenceVerdict(outcomes, k, { lambda: 0 }), { lambda: 1 }, { lambda: 1.5 }, or { lambda: -0.1 }. Flow comes from PromoteOptions.sequentialLambda through the promotion path.
Common situations: A misconfigured sequentialLambda passed via the promotion command; a config file that set lambda to 0 thinking it disables the check; a tuning experiment with an out-of-range value.
Related errors
- testIndex must be a positive integer
- testsRun must be a non-negative integer
- metric must be finite
- bootstrap iterations must be >= 100
- unknown game "${key}". Known: ${Object.keys(GAMES).join(', '
AI-assisted analysis of ruvnet/ruflo@6b01dc5a68 (2026-08-12).
Data as JSON: /api/errors/76096b4f024ba6d9.
Report an issue: GitHub.