{"record":{"id":"72846680c8730abc","repo":"caolan/async","slug":"concurrency-limit-cannot-be-less-than-1","errorCode":null,"errorMessage":"concurrency limit cannot be less than 1","messagePattern":"concurrency limit cannot be less than 1","errorType":"validation","errorClass":"RangeError","httpStatus":null,"severity":"error","filePath":"lib/internal/eachOfLimit.js","lineNumber":12,"sourceCode":"import once from './once.js'\nimport iterator from './iterator.js'\nimport onlyOnce from './onlyOnce.js'\nimport {isAsyncGenerator, isAsyncIterable} from './wrapAsync.js'\nimport asyncEachOfLimit from './asyncEachOfLimit.js'\nimport breakLoop from './breakLoop.js'\n\nexport default (limit) => {\n    return (obj, iteratee, callback) => {\n        callback = once(callback);\n        if (limit <= 0) {\n            throw new RangeError('concurrency limit cannot be less than 1')\n        }\n        if (!obj) {\n            return callback(null);\n        }\n        if (isAsyncGenerator(obj)) {\n            return asyncEachOfLimit(obj, limit, iteratee, callback)\n        }\n        if (isAsyncIterable(obj)) {\n            return asyncEachOfLimit(obj[Symbol.asyncIterator](), limit, iteratee, callback)\n        }\n        var nextElem = iterator(obj);\n        var done = false;\n        var canceled = false;\n        var running = 0;\n        var looping = false;\n\n        function iterateeCallback(err, value) {\n            if (canceled) return","sourceCodeStart":1,"sourceCodeEnd":30,"githubUrl":"https://github.com/caolan/async/blob/13dfaf13f3fc809ba1c9c39d5e267ac6959cbf4a/lib/internal/eachOfLimit.js#L1-L30","documentation":"The shared worker underlying eachOfLimit/eachLimit/mapLimit etc. validates the concurrency argument. A limit of 0 or negative would mean no worker can ever run, so a RangeError is thrown immediately. The limit must be a positive integer.","triggerScenarios":"Calling async.eachLimit(coll, 0, iteratee), async.mapLimit(coll, -1, fn), or passing a computed concurrency value that evaluates to 0 (e.g. Math.ceil(list.length / 0), an unset config variable defaulting to 0).","commonSituations":"Config value like CONCURRENCY=0 from environment, division producing 0/NaN, off-by-one when computing parallelism from CPU count, copying examples and setting limit 0 to mean 'unlimited' (it does not — use each/map instead).","solutions":["Pass a positive integer, e.g. Math.max(1, configuredLimit)","For unlimited concurrency use async.each/async.map instead of the Limit variants","Validate/normalize config before calling: limit = Number(cfg) > 0 ? Number(cfg) : 1","Fix the computation producing 0 or NaN"],"exampleFix":"// before\nawait async.mapLimit(items, config.concurrency, mapper);\n// after\nconst limit = Math.max(1, parseInt(config.concurrency, 10) || 1);\nawait async.mapLimit(items, limit, mapper);","handlingStrategy":"validation","validationCode":"const assertLimit = (n) => { const v = Number(n); if (!Number.isInteger(v) || v < 1) throw new RangeError('concurrency limit cannot be less than 1'); return v; };","typeGuard":"function isValidLimit(n) {\n  return Number.isInteger(n) && n >= 1;\n}","tryCatchPattern":"try {\n  await async.mapLimit(items, limit, mapper);\n} catch (err) {\n  if (err instanceof RangeError) {\n    return async.map(items, mapper); // unlimited fallback\n  }\n  throw err;\n}","preventionTips":["Normalize configured concurrency with Math.max(1, value)","Use plain each/map when you want unlimited concurrency","Add unit tests covering concurrency config edge values"],"tags":["async","concurrency","range-error"],"backgroundTag":"invalid-concurrency-limit","analyzedSha":"13dfaf13f3fc809ba1c9c39d5e267ac6959cbf4a","analyzedAt":"2026-08-28T22:50:46.507Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}