mongodb/node-mongodb-native · error · MongoInvalidArgumentError

Argument "size" must be a non-negative number

Error message

Argument "size" must be a non-negative number

What it means

Thrown by the internal message-buffer read() method when the size argument is not a number or is negative. This Buffer/MessageStream utility reads a fixed number of bytes from a queue; a non-numeric or negative size is invalid. Raised as MongoInvalidArgumentError. This is an internal API not invoked directly by users.

Solutions

  1. Upgrade the driver to the latest stable release; internal buffer bugs are fixed upstream.
  2. If behind a proxy or mongos/router, ensure it emits valid MongoDB wire-protocol responses.
  3. Capture the full stack trace and report to the NODE driver Jira project.
Defensive patterns

Strategy: try-catch

Try / catch

try {
  await client.db('test').command({ ping: 1 });
} catch (e) {
  if (e instanceof MongoInvalidArgumentError && /size.*non-negative/.test(e.message)) {
    // internal buffer error: upgrade driver, check proxy/server compatibility
  } else throw e;
}

Prevention

When it happens

Trigger: Internal driver wire-protocol parsing code calling read() with an undefined or negative size, typically due to a malformed message length header from the server or a corrupted buffer state. Not reachable through normal user API calls.

Common situations: Extremely rare. May surface if a custom wire-protocol interceptor or proxy sends malformed responses, or from driver bugs in buffer handling. Indicates corruption in the incoming byte stream or an internal logic error.

Related errors


AI-assisted analysis of mongodb/node-mongodb-native@dce7939f86 (2026-08-11). Data as JSON: /api/errors/31e7bb5461623773. Report an issue: GitHub.

Appendix: source

Thrown at src/utils.ts:840

      return NumberUtils.getInt32LE(firstBuffer, 0);
    }

    // Unlikely case: an int32 is split across buffers.
    // Use read and put the returned buffer back on top
    const top4Bytes = this.read(4);
    const value = NumberUtils.getInt32LE(top4Bytes, 0);

    // Put it back.
    this.totalByteLength += 4;
    this.buffers.unshift(top4Bytes);

    return value;
  }

  /** Reads the requested number of bytes, optionally consuming them */
  read(size: number): Uint8Array {
    if (typeof size !== 'number' || size < 0) {
      throw new MongoInvalidArgumentError('Argument "size" must be a non-negative number');
    }

    // oversized request returns empty buffer
    if (size > this.totalByteLength) {
      return ByteUtils.allocate(0);
    }

    // We know we have enough, we just don't know how it is spread across chunks
    // TODO(NODE-4732): alloc API should change based on raw option
    const result = ByteUtils.allocateUnsafe(size);

    for (let bytesRead = 0; bytesRead < size; ) {
      const buffer = this.buffers.shift();
      if (buffer == null) {
        break;
      }
      const bytesRemaining = size - bytesRead;
      const bytesReadable = Math.min(bytesRemaining, buffer.byteLength);

View on GitHub (pinned to dce7939f86)