caolan/async · error · RangeError
concurrency limit cannot be less than 1
Error message
concurrency limit cannot be less than 1
What it means
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.
Source
Thrown at lib/internal/eachOfLimit.js:12
import once from './once.js'
import iterator from './iterator.js'
import onlyOnce from './onlyOnce.js'
import {isAsyncGenerator, isAsyncIterable} from './wrapAsync.js'
import asyncEachOfLimit from './asyncEachOfLimit.js'
import breakLoop from './breakLoop.js'
export default (limit) => {
return (obj, iteratee, callback) => {
callback = once(callback);
if (limit <= 0) {
throw new RangeError('concurrency limit cannot be less than 1')
}
if (!obj) {
return callback(null);
}
if (isAsyncGenerator(obj)) {
return asyncEachOfLimit(obj, limit, iteratee, callback)
}
if (isAsyncIterable(obj)) {
return asyncEachOfLimit(obj[Symbol.asyncIterator](), limit, iteratee, callback)
}
var nextElem = iterator(obj);
var done = false;
var canceled = false;
var running = 0;
var looping = false;
function iterateeCallback(err, value) {
if (canceled) returnView on GitHub (pinned to 13dfaf13f3)
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
Example fix
// before await async.mapLimit(items, config.concurrency, mapper); // after const limit = Math.max(1, parseInt(config.concurrency, 10) || 1); await async.mapLimit(items, limit, mapper);
Defensive patterns
Strategy: validation
Validate before calling
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; }; Type guard
function isValidLimit(n) {
return Number.isInteger(n) && n >= 1;
} Try / catch
try {
await async.mapLimit(items, limit, mapper);
} catch (err) {
if (err instanceof RangeError) {
return async.map(items, mapper); // unlimited fallback
}
throw err;
} Prevention
- 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
When it happens
Trigger: 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).
Common situations: 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).
Related errors
- Concurrency must not be zero
- async.auto task `${key}` has a non-existent dependency `${de
- async.auto cannot execute tasks due to a recursive dependenc
- could not parse args in autoInject Source: ${src}
- autoInject task functions require explicit parameters.
AI-assisted analysis of caolan/async@13dfaf13f3 (2026-08-28).
Data as JSON: /api/errors/72846680c8730abc.
Report an issue: GitHub.