t8y2/dbx · error · IllegalArgumentException

MongoDB Legacy aggregate option hint must be an object

Error message

MongoDB Legacy aggregate option hint must be an object

What it means

The 'hint' aggregate option must be a Document (an index-key pattern object) because it is cast to Document and passed to AggregateIterable.hint(Document). Any other type (string index name, number) fails the instanceof check and IllegalArgumentException is thrown. The message mentions 'Legacy' because this code path uses the legacy Document-based hint API.

Source

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

        }
        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(
            "explain",
            "allowDiskUse",
            "cursor",
            "maxTimeMS",
            "maxAwaitTimeMS",
            "bypassDocumentValidation",
            "collation",

View on GitHub (pinned to c0390bff16)

Solutions

  1. Pass the hint as an index key pattern Document: new Document("field", 1) / {"hint":{"field":1}}.
  2. If you only know the index name, resolve it to its key pattern (or use a driver API accepting an index-name Bson if available in a newer driver).
  3. Parse a JSON key pattern with Document.parse("{\"age\": 1}").
  4. Omit hint to let the planner choose.

Example fix

// before
Document options = new Document("hint", "age_index_1");
// after
Document options = new Document("hint", new Document("age", 1));
Defensive patterns

Strategy: validation

Validate before calling

Object hint = options.get("hint");
if (hint != null && !(hint instanceof Document)) {
    throw new IllegalArgumentException("hint must be an index key pattern object like {field:1}");
}

Type guard

static boolean isDocument(Object v) {
    return v == null || v instanceof Document;
}

Try / catch

try {
    agent.aggregate(db, collection, pipeline, options);
} catch (IllegalArgumentException e) {
    if (e.getMessage().contains("hint must be an object")) {
        // cannot safely convert an index name to a key pattern — reject or resolve via listIndexes
        throw new IllegalStateException("Resolve index name to its key pattern before hinting");
    } else throw e;
}

Prevention

When it happens

Trigger: Calling aggregate with options like {"hint":"age_index_1"} (index name string) or {"hint":1} instead of an object such as {"hint":{"age":1}}.

Common situations: Using the shell-style index NAME string, which the legacy hint(Document) overload does not accept; building hint from a flat config string; confusion between hint-by-name and hint-by-key-pattern.

Related errors


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