Automattic/mongoose · error · TypeError

batchSize must be at least 1

Error message

batchSize must be at least 1

What it means

eachAsync rejects batchSize values below 1: 0 and negative numbers throw TypeError('batchSize must be at least 1'). batchSize of 0 usually means the developer intended no batching or driver default, but the server requires at least one document per batch, so Mongoose validates the lower bound eagerly.

Source

Thrown at lib/helpers/cursor/eachAsync.js:54

  return new Promise((resolve, reject) => {
    if (signal != null) {
      if (signal.aborted) {
        return resolve(null);
      }

      signal.addEventListener('abort', () => {
        aborted = true;
        return resolve(null);
      }, { once: true });
    }

    if (batchSize != null) {
      if (typeof batchSize !== 'number') {
        throw new TypeError('batchSize must be a number');
      } else if (!Number.isInteger(batchSize)) {
        throw new TypeError('batchSize must be an integer');
      } else if (batchSize < 1) {
        throw new TypeError('batchSize must be at least 1');
      }
    }

    iterate((err, res) => {
      if (err != null) {
        return reject(err);
      }
      resolve(res);
    });
  });

  function iterate(finalCallback) {
    let handleResultsInProgress = 0;
    let currentDocumentIndex = 0;

    let error = null;
    for (let i = 0; i < parallel; ++i) {
      enqueue(createFetch());

View on GitHub (pinned to 49cdab0136)

Solutions

  1. Treat 0/negative as unset: const opts = n > 0 ? { batchSize: n } : {};.
  2. Or clamp: batchSize: Math.max(1, n).
  3. Fix the source producing non-positive values (env defaults, empty-length divisions).

Example fix

// before
const batchSize = Number(process.env.BATCH_SIZE ?? 0);
await cursor.eachAsync(fn, { batchSize }); // 0 -> TypeError

// after
const raw = Number(process.env.BATCH_SIZE ?? NaN);
const batchSize = Number.isInteger(raw) && raw >= 1 ? raw : undefined;
await cursor.eachAsync(fn, { batchSize }); // undefined = driver default
Defensive patterns

Strategy: validation

Validate before calling

function toBatchSize(v) {
  const n = v == null ? NaN : Number(v);
  return Number.isInteger(n) && n >= 1 ? n : undefined; // undefined = driver default
}
await cursor.eachAsync(fn, { batchSize: toBatchSize(process.env.BATCH_SIZE) });

Type guard

function isValidBatchSize(v) {
  return typeof v === 'number' && Number.isInteger(v) && v >= 1;
}

Prevention

When it happens

Trigger: cursor.eachAsync(fn, { batchSize: 0 }) intending unlimited; negative values from misconfigured env vars or arithmetic underflow; -1 sentinels copied from a different API's semantics.

Common situations: Env var defaulting to 0 when unset; computed batch sizes that reach 0 for empty inputs; conventions from other libraries where 0 means default.

Related errors


AI-assisted analysis of Automattic/mongoose@49cdab0136 (2026-08-21). Data as JSON: /api/errors/96095913694bae8a. Report an issue: GitHub.