{"record":{"id":"efd04ad1290f1a1d","repo":"mongodb/node-mongodb-native","slug":"uri-option-key-cannot-appear-more-than-once-i","errorCode":null,"errorMessage":"URI option \"${key}\" cannot appear more than once in the connection string","messagePattern":"URI option \"(.+?)\" cannot appear more than once in the connection string","errorType":"exception","errorClass":"MongoInvalidArgumentError","httpStatus":null,"severity":"error","filePath":"src/connection_string.ts","lineNumber":292,"sourceCode":"  if (url.username !== '') {\n    const auth: Document = {\n      username: decodeURIComponent(url.username)\n    };\n\n    if (typeof url.password === 'string') {\n      auth.password = decodeURIComponent(url.password);\n    }\n\n    urlOptions.set('auth', [auth]);\n  }\n\n  for (const key of url.searchParams.keys()) {\n    const values = url.searchParams.getAll(key);\n\n    const isReadPreferenceTags = /readPreferenceTags/i.test(key);\n\n    if (!isReadPreferenceTags && values.length > 1) {\n      throw new MongoInvalidArgumentError(\n        `URI option \"${key}\" cannot appear more than once in the connection string`\n      );\n    }\n\n    if (!isReadPreferenceTags && values.includes('')) {\n      throw new MongoAPIError(`URI option \"${key}\" cannot be specified with no value`);\n    }\n\n    if (!urlOptions.has(key)) {\n      urlOptions.set(key, values);\n    }\n  }\n\n  const objectOptions = new CaseInsensitiveMap<unknown>(\n    Object.entries(options).filter(([, v]) => v != null)\n  );\n\n  // Validate options that can only be provided by one of uri or object","sourceCodeStart":274,"sourceCodeEnd":310,"githubUrl":"https://github.com/mongodb/node-mongodb-native/blob/dce7939f86fb283e167ad709955abedb7bf23124/src/connection_string.ts#L274-L310","documentation":"With the exception of readPreferenceTags, each URI query parameter may appear at most once. The driver collects all values per key; if a non-readPreferenceTags key has more than one value, it throws MongoInvalidArgumentError to avoid silent ambiguity about which value wins.","triggerScenarios":"A URI like 'mongodb://h/db?retryWrites=true&retryWrites=false' or 'mongodb://h/db?appname=a&appname=b'. Triggered while iterating url.searchParams.keys().","commonSituations":"Concatenating query strings, templating bugs that append the same param twice, or merging config fragments without deduping.","solutions":["Search the URI for the duplicated key and keep a single occurrence.","Generate connection strings from a single options object rather than string concatenation."],"exampleFix":"// before\n'mongodb://h/db?retryWrites=true&retryWrites=false'\n// after\n'mongodb://h/db?retryWrites=true'","handlingStrategy":"validation","validationCode":"function assertNoDuplicateQueryKeys(uri: string) {\n  const q = uri.split('?')[1];\n  if (!q) return;\n  const seen = new Set<string>();\n  for (const pair of q.split('&')) {\n    const key = pair.split('=')[0];\n    if (!key) continue;\n    if (key === 'readPreferenceTags') continue;\n    if (seen.has(key)) throw new Error(`Duplicate URI option '${key}'`);\n    seen.add(key);\n  }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Build URIs from a Map/options object rather than string concatenation.","Lint connection strings in CI for duplicate keys."],"tags":["connection-string","validation","uri"],"backgroundTag":null,"analyzedSha":"dce7939f86fb283e167ad709955abedb7bf23124","analyzedAt":"2026-08-11T04:54:53.215Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}