{"record":{"id":"cf0d9bcd59658537","repo":"t8y2/dbx","slug":"mongodb-aggregate-option-key-must-be-a-non-nega","errorCode":null,"errorMessage":"MongoDB aggregate option ${key} must be a non-negative integer","messagePattern":"MongoDB aggregate option (.+?) must be a non-negative integer","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"agents/drivers/mongodb/src/main/java/com/dbx/agent/mongodb/MongoAgent.java","lineNumber":673,"sourceCode":"        Object value = options.get(key);\n        if (!(value instanceof Boolean)) {\n            throw new IllegalArgumentException(\"MongoDB aggregate option \" + key + \" must be a boolean\");\n        }\n        return (Boolean) value;\n    }\n\n    private static int aggregateNonNegativeInt(Document options, String key) {\n        long value = aggregateNonNegativeLong(options, key);\n        if (value > Integer.MAX_VALUE) {\n            throw new IllegalArgumentException(\"MongoDB aggregate option \" + key + \" is too large\");\n        }\n        return (int) value;\n    }\n\n    private static long aggregateNonNegativeLong(Document options, String key) {\n        Object value = options.get(key);\n        if (!(value instanceof Number number) || number.doubleValue() != Math.rint(number.doubleValue())) {\n            throw new IllegalArgumentException(\"MongoDB aggregate option \" + key + \" must be a non-negative integer\");\n        }\n        long result = number.longValue();\n        if (result < 0) {\n            throw new IllegalArgumentException(\"MongoDB aggregate option \" + key + \" must be a non-negative integer\");\n        }\n        return result;\n    }\n\n    static Document buildFindExplainCommand(JsonObject params) {\n        String collection = params.get(\"collection\").getAsString();\n        Document find = new Document(\"find\", collection);\n        Document filter = documentOrNull(params, \"filter\");\n        find.append(\"filter\", filter == null ? new Document() : filter);\n\n        Document projection = documentOrNull(params, \"projection\");\n        if (projection != null) {\n            find.append(\"projection\", projection);\n        }","sourceCodeStart":655,"sourceCodeEnd":691,"githubUrl":"https://github.com/t8y2/dbx/blob/c0390bff16418b651f4728520d99adf8ce48829a/agents/drivers/mongodb/src/main/java/com/dbx/agent/mongodb/MongoAgent.java#L655-L691","documentation":"MongoAgent validates aggregate options such as batchSize, maxTimeMS, maxAwaitTimeMS, or allowDiskUse-sized values with this helper. The option must be a Number whose value is a whole number and not negative. Anything else (string, fractional, negative, non-number type) throws this IllegalArgumentException before the command is sent to MongoDB.","triggerScenarios":"Calling the aggregate operation with options like batchSize or maxTimeMS passed as a string (e.g. \"1000\"), as a float (e.g. 100.5), or as a negative number (e.g. -1).","commonSituations":"Options parsed from JSON/HTTP query params where numbers arrive as strings; copying batchSize values from shell examples that allow negatives or floats; config files edited by hand.","solutions":["Pass the option as an actual integer number type, not a string","Ensure the value is a whole number (no fractional part)","Clamp or omit negative values; check value >= 0 before calling","Validate options in the caller before sending to the agent"],"exampleFix":"// before\n{\"collection\":\"orders\",\"pipeline\":[],\"options\":{\"batchSize\":\"100\"}}\n// after\n{\"collection\":\"orders\",\"pipeline\":[],\"options\":{\"batchSize\":100}}","handlingStrategy":"validation","validationCode":"function isValidNonNegativeInt(v) {\n  return typeof v === 'number' && Number.isInteger(v) && v >= 0;\n}\n// before calling: if (opts.batchSize != null && !isValidNonNegativeInt(opts.batchSize)) throw ...","typeGuard":"function isNonNegativeInteger(v) {\n  return typeof v === 'number' && Number.isInteger(v) && v >= 0;\n}","tryCatchPattern":"try {\n  result = agent.aggregate(params);\n} catch (IllegalArgumentException e) {\n  if (e.getMessage().contains(\"must be a non-negative integer\")) {\n    // sanitize options and retry once with defaults\n  } else throw e;\n}","preventionTips":["Never pass numeric options as strings from JSON/query params","Parse with Number()/parseInt and verify with Number.isInteger","Sanitize user-supplied aggregate options against a whitelist","Add pre-call assertions for batchSize and maxTimeMS"],"tags":["mongodb","aggregate","validation","options"],"backgroundTag":"invalid-option-value","analyzedSha":"c0390bff16418b651f4728520d99adf8ce48829a","analyzedAt":"2026-09-05T23:05:10.900Z","contentChangedAt":"2026-09-05T23:05:10.900Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}