t8y2/dbx · error · IllegalArgumentException

MongoDB aggregate option comment must be a string

Error message

MongoDB aggregate option comment must be a string

What it means

The 'comment' aggregate option must be a Java String because it is passed to AggregateIterable.comment(String). Any non-string value (number, boolean, Document) fails the instanceof check and IllegalArgumentException is thrown before execution.

Source

Thrown at agents/drivers/mongodb/src/main/java/com/dbx/agent/mongodb/MongoAgent.java:609

            iterable = iterable.maxAwaitTime(
                aggregateNonNegativeLong(options, "maxAwaitTimeMS"),
                TimeUnit.MILLISECONDS
            );
        }
        if (options.containsKey("bypassDocumentValidation")) {
            iterable = iterable.bypassDocumentValidation(aggregateBoolean(options, "bypassDocumentValidation"));
        }
        if (options.containsKey("collation")) {
            Object rawCollation = options.get("collation");
            if (!(rawCollation instanceof Document collation)) {
                throw new IllegalArgumentException("MongoDB aggregate option collation must be an object");
            }
            iterable = iterable.collation(collationOrNull(collation));
        }
        if (options.containsKey("comment")) {
            Object comment = options.get("comment");
            if (!(comment instanceof String)) {
                throw new IllegalArgumentException("MongoDB aggregate option comment must be a string");
            }
            iterable = iterable.comment((String) comment);
        }
        if (options.containsKey("hint")) {
            Object hint = options.get("hint");
            if (!(hint instanceof Document)) {
                throw new IllegalArgumentException("MongoDB Legacy aggregate option hint must be an object");
            }
            iterable = iterable.hint((Document) hint);
        }
        if (options.containsKey("useCursor")) {
            iterable = iterable.useCursor(aggregateBoolean(options, "useCursor"));
        }
        return iterable;
    }

    private static void validateAggregateOptions(Document options) {
        Set<String> supported = Set.of(

View on GitHub (pinned to c0390bff16)

Solutions

  1. Convert the value to a string before setting it: new Document("comment", String.valueOf(value)).
  2. Use a descriptive string comment suitable for profiling/ops tracing.
  3. Drop the comment option if it is not needed.
  4. Coerce at the config boundary where the options Document is built.

Example fix

// before
Document options = new Document("comment", requestId); // requestId is long
// after
Document options = new Document("comment", String.valueOf(requestId));
Defensive patterns

Strategy: validation

Validate before calling

Object comment = options.get("comment");
if (comment != null && !(comment instanceof String)) {
    throw new IllegalArgumentException("comment must be a string, got: " + comment.getClass().getSimpleName());
}

Type guard

static boolean isString(Object v) {
    return v == null || v instanceof String;
}

Try / catch

try {
    agent.aggregate(db, collection, pipeline, options);
} catch (IllegalArgumentException e) {
    if (e.getMessage().contains("comment must be a string")) {
        options.put("comment", String.valueOf(options.get("comment")));
        // retry
    } else throw e;
}

Prevention

When it happens

Trigger: Calling aggregate with options like {"comment": 12345} or {"comment": true} instead of a string such as {"comment":"nightly report run"}.

Common situations: Auto-generated IDs (numbers) used as comments without String.valueOf(); JSON from a loosely-typed producer where the comment field was numeric; copying from code that used the numeric comment variant of the server command.

Related errors


AI-assisted analysis of t8y2/dbx@c0390bff16 (2026-09-05). Data as JSON: /api/errors/26780b0629066acd. Report an issue: GitHub.