mongodb/node-mongodb-native · error · MongoInvalidArgumentError

Option "explain" is not supported on this command

Error message

Option "explain" is not supported on this command

What it means

Thrown by the CommandOperation base constructor when an `explain` option is supplied for an operation that does not declare the EXPLAINABLE aspect. Only certain operations (find, aggregate, count, etc.) can be explained; passing explain to others is meaningless and rejected as MongoInvalidArgumentError before execution.

Source

Thrown at src/operations/command.ts:104

    //       something we'd want to reconsider. Perhaps those commands can use `Admin`
    //       as a parent?
    const dbNameOverride = options?.dbName || options?.authdb;
    if (dbNameOverride) {
      this.ns = new MongoDBNamespace(dbNameOverride, '$cmd');
    } else {
      this.ns = parent
        ? parent.s.namespace.withCollection('$cmd')
        : new MongoDBNamespace('admin', '$cmd');
    }

    this.readConcern = ReadConcern.fromOptions(options);
    this.writeConcern = WriteConcern.fromOptions(options);

    if (this.hasAspect(Aspect.EXPLAINABLE)) {
      this.explain = Explain.fromOptions(options);
      if (this.explain) validateExplainTimeoutOptions(this.options, this.explain);
    } else if (options?.explain != null) {
      throw new MongoInvalidArgumentError(`Option "explain" is not supported on this command`);
    }
  }

  override get canRetryWrite(): boolean {
    if (this.hasAspect(Aspect.EXPLAINABLE)) {
      return this.explain == null;
    }
    return super.canRetryWrite;
  }

  abstract buildCommandDocument(connection: Connection, session?: ClientSession): Document;

  override buildOptions(timeoutContext: TimeoutContext): ServerCommandOptions {
    return {
      ...this.options,
      ...this.bsonOptions,
      timeoutContext,
      readPreference: this.readPreference,

View on GitHub (pinned to 3366c21a63)

Solutions

  1. Remove the explain option from non-explainable operations.
  2. Only use explain with supported operations: find, aggregate, countDocuments (via aggregate), and distinct.
  3. If using a shared options builder, branch on operation type before adding explain.

Example fix

// before
await collection.insertOne(doc, { explain: true }); // throws

// after
await collection.insertOne(doc);
// explain only where supported:
await collection.find({}).explain();
Defensive patterns

Strategy: validation

Validate before calling

const EXPLAINABLE = new Set(['find','aggregate','count','distinct']);
if (!EXPLAINABLE.has(opName)) delete options.explain;

Type guard

function isExplainable(opName): boolean {
  return ['find','aggregate','count','distinct'].includes(opName);
}

Prevention

When it happens

Trigger: Passing { explain: true } (or a verbosity value) to collection.insertOne, updateMany, createIndex, command runners, or any non-explainable operation. Spreading a shared options object that includes explain across all calls.

Common situations: Generic option-merging helpers that attach explain everywhere; debugging code that wraps every operation with explain; copy-paste from an aggregate call.

Related errors


AI-assisted analysis of mongodb/node-mongodb-native@3366c21a63 (2026-08-04). Data as JSON: /data/errors/62051f66ac0921cb.json. Report an issue: GitHub.