{"record":{"id":"500062dd816b8147","repo":"t8y2/dbx","slug":"index-options-cannot-contain-key-specify-index","errorCode":null,"errorMessage":"Index options cannot contain \"key\"; specify index fields in keys JSON","messagePattern":"Index options cannot contain \"key\"; specify index fields in keys JSON","errorType":"validation","errorClass":"java.lang.IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"agents/drivers/mongodb/src/main/java/com/dbx/agent/mongodb/MongoAgent.java","lineNumber":1010,"sourceCode":"            // Without an explicit old version, preserve MongoDB's single-command array semantics.\n            return false;\n        }\n    }\n\n    private static Object createIndex(JsonObject params) {\n        MongoClient c = requireClient();\n        String database = params.get(\"database\").getAsString();\n        String collection = params.get(\"collection\").getAsString();\n        Document keys = requiredDocument(params, \"keys_json\", \"Index keys\");\n        if (keys.isEmpty()) {\n            throw new IllegalArgumentException(\"Index keys are required\");\n        }\n\n        Document index = new Document(\"key\", keys);\n        Document options = documentOrNull(params, \"options_json\");\n        if (options != null) {\n            if (options.containsKey(\"key\")) {\n                throw new IllegalArgumentException(\"Index options cannot contain \\\"key\\\"; specify index fields in keys JSON\");\n            }\n            index.putAll(options);\n        }\n        String name;\n        if (!index.containsKey(\"name\")) {\n            name = defaultIndexName(keys);\n            index.put(\"name\", name);\n        } else if (!(index.get(\"name\") instanceof String)) {\n            throw new IllegalArgumentException(\"Index option \\\"name\\\" must be a non-empty string\");\n        } else {\n            name = (String) index.get(\"name\");\n            if (name.isBlank()) {\n                throw new IllegalArgumentException(\"Index option \\\"name\\\" must be a non-empty string\");\n            }\n        }\n\n        c.getDatabase(database).runCommand(\n            new Document(\"createIndexes\", collection)","sourceCodeStart":992,"sourceCodeEnd":1028,"githubUrl":"https://github.com/t8y2/dbx/blob/c0390bff16418b651f4728520d99adf8ce48829a/agents/drivers/mongodb/src/main/java/com/dbx/agent/mongodb/MongoAgent.java#L992-L1028","documentation":"In createIndex, index fields must be given via keys_json; the options_json document is merged into the index spec, so an option named \"key\" would collide with the required \"key\" field and corrupt the specification. The agent therefore rejects options containing a \"key\" entry with IllegalArgumentException. This is a schema conflict guard, not a MongoDB server rule.","triggerScenarios":"Calling createIndex with options_json that includes a \"key\" field, e.g. {\"options_json\": {\"key\": {\"field\": 1}, \"unique\": true}}.","commonSituations":"Confusing keys and options — putting index fields into options_json instead of keys_json; merging a full index spec (as returned by getIndexes) into options; copy-paste from server-side index documents.","solutions":["Move the key fields out of options_json into keys_json, keeping only true options (unique, name, expireAfterSeconds, etc.) in options_json.","If you have a full index spec, split it: \"key\" goes to keys_json, everything else to options_json.","Validate the options map before sending to ensure it has no \"key\" entry."],"exampleFix":"// before\n{\"keys_json\": {}, \"options_json\": {\"key\": {\"email\": 1}, \"unique\": true}}\n// after\n{\"keys_json\": {\"email\": 1}, \"options_json\": {\"unique\": true}}","handlingStrategy":"validation","validationCode":"if (params.options_json && \"key\" in params.options_json) {\n  // move it: params.keys_json = params.options_json.key; delete params.options_json.key;\n  throw new Error(\"Move index fields from options_json.key into keys_json\");\n}","typeGuard":"function optionsHaveNoKey(options) {\n  return options == null || !(\"key\" in options);\n}","tryCatchPattern":"try {\n  await agent.createIndex({ database, collection, keys_json: keys, options_json: options });\n} catch (e) {\n  if (String(e.message).includes('cannot contain \"key\"')) {\n    const { key, ...rest } = options; // split and retry\n    await agent.createIndex({ database, collection, keys_json: key, options_json: rest });\n  } else throw e;\n}","preventionTips":["Never merge a raw index spec (from getIndexes) into options_json; split key out first.","Keep index fields only in keys_json and true options (unique, name, expireAfterSeconds) in options_json.","Add a pre-send check that options_json has no \"key\" property."],"tags":["mongodb","index","validation","schema-conflict"],"backgroundTag":"invalid-parameter-conflict","analyzedSha":"c0390bff16418b651f4728520d99adf8ce48829a","analyzedAt":"2026-09-05T23:05:10.900Z","contentChangedAt":"2026-09-05T23:05:10.900Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}