{"record":{"id":"ea1cbc7172877816","repo":"ruvnet/ruflo","slug":"maxconcurrency-must-be-a-positive-integer","errorCode":null,"errorMessage":"maxConcurrency must be a positive integer","messagePattern":"maxConcurrency must be a positive integer","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"v3/@claude-flow/cli/src/services/bounded-worker-pool.ts","lineNumber":32,"sourceCode":"  results: BoundedTaskResult<T>[];\n  peakConcurrency: number;\n  durationMs: number;\n}\n\n/**\n * Deterministic bounded worker pool for Codex/MetaHarness fanout.\n *\n * Completion order never affects result order. The caller-supplied AbortSignal\n * and timeout cancel both queued and cooperative running work. No unbounded\n * Promise.all is used.\n */\nexport async function runBoundedPool<T>(\n  tasks: readonly BoundedTask<T>[],\n  options: { maxConcurrency: number; timeoutMs?: number; signal?: AbortSignal },\n): Promise<BoundedPoolResult<T>> {\n  const started = Date.now();\n  if (!Number.isInteger(options.maxConcurrency) || options.maxConcurrency < 1) {\n    throw new Error('maxConcurrency must be a positive integer');\n  }\n  const ids = new Set<string>();\n  for (const task of tasks) {\n    if (!task.id || ids.has(task.id)) throw new Error(`duplicate or empty task id: ${task.id}`);\n    ids.add(task.id);\n  }\n  const maxConcurrency = Math.min(options.maxConcurrency, tasks.length || 1);\n  const controller = new AbortController();\n  const onAbort = () => controller.abort(options.signal?.reason ?? new Error('cancelled'));\n  options.signal?.addEventListener('abort', onAbort, { once: true });\n  const timer = options.timeoutMs && options.timeoutMs > 0\n    ? setTimeout(() => controller.abort(new Error('worker-pool-timeout')), options.timeoutMs)\n    : undefined;\n\n  const results = new Map<string, BoundedTaskResult<T>>();\n  let cursor = 0;\n  let active = 0;\n  let peakConcurrency = 0;","sourceCodeStart":14,"sourceCodeEnd":50,"githubUrl":"https://github.com/ruvnet/ruflo/blob/6b01dc5a687b26b3e218f796de45ec51f8fa9e8c/v3/@claude-flow/cli/src/services/bounded-worker-pool.ts#L14-L50","documentation":"runBoundedPool requires options.maxConcurrency to be a positive integer (Number.isInteger AND >= 1). Fractional, zero, negative, NaN, or undefined values throw before any task runs, so no partial work is started. The check is intentionally strict because the pool's correctness (deterministic order, cap enforcement) depends on an integer concurrency.","triggerScenarios":"Calling runBoundedPool(tasks, { maxConcurrency: 0 }), with a float like 2.5, with NaN (often from a bad parseInt), or omitting the option so it is undefined.","commonSituations":"Reading concurrency from an env var without validation (Number('') === 0, Number(undefined) === NaN); computing maxConcurrency as tasks.length / workers without Math.ceil; defaulting to 0 when no workers configured.","solutions":["Compute concurrency defensively: Math.max(1, Math.floor(value)) and validate isFinite first.","Validate env-derived concurrency before passing it in.","Pick a sane default (e.g., os.cpus().length) when the configured value is invalid."],"exampleFix":"// before\nconst pool = await runBoundedPool(tasks, { maxConcurrency: Number(process.env.WORKERS) });\n// WORKERS unset -> NaN -> throws\n\n// after\nconst raw = Number(process.env.WORKERS);\nconst maxConcurrency = Number.isFinite(raw) && raw >= 1 ? Math.floor(raw) : 4;\nconst pool = await runBoundedPool(tasks, { maxConcurrency, timeoutMs: 30000 });","handlingStrategy":"validation","validationCode":"function safeConcurrency(raw, fallback = 4) {\n  const n = Number(raw);\n  return Number.isInteger(n) && n >= 1 ? n : fallback;\n}","typeGuard":"function isPositiveInt(n): n is number {\n  return typeof n === 'number' && Number.isInteger(n) && n >= 1;\n}","tryCatchPattern":null,"preventionTips":["Never pass raw env-derived numbers straight into options; coerce and validate first.","Default to a known good value (os.cpus().length) when parsing fails.","Beware Number(undefined) === NaN and Number('') === 0."],"tags":["validation","worker-pool","concurrency","config"],"backgroundTag":null,"analyzedSha":"6b01dc5a687b26b3e218f796de45ec51f8fa9e8c","analyzedAt":"2026-08-12T13:20:50.148Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}