{"id":"342c261bb0d91d1a","repo":"brianc/node-postgres","slug":"both-uselibpqcompat-and-uselibpqcompat-are-set-pl","errorCode":null,"errorMessage":"Both useLibpqCompat and uselibpqcompat are set. Please use only one of them.","messagePattern":"Both useLibpqCompat and uselibpqcompat are set\\. Please use only one of them\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/pg-connection-string/index.js","lineNumber":103,"sourceCode":"  }\n\n  // Only try to load fs if we expect to read from the disk\n  const fs = config.sslcert || config.sslkey || config.sslrootcert ? require('fs') : null\n\n  if (config.sslcert) {\n    config.ssl.cert = fs.readFileSync(config.sslcert).toString()\n  }\n\n  if (config.sslkey) {\n    config.ssl.key = fs.readFileSync(config.sslkey).toString()\n  }\n\n  if (config.sslrootcert) {\n    config.ssl.ca = fs.readFileSync(config.sslrootcert).toString()\n  }\n\n  if (options.useLibpqCompat && config.uselibpqcompat) {\n    throw new Error('Both useLibpqCompat and uselibpqcompat are set. Please use only one of them.')\n  }\n\n  if (config.uselibpqcompat === 'true' || options.useLibpqCompat) {\n    switch (config.sslmode) {\n      case 'disable': {\n        config.ssl = false\n        break\n      }\n      case 'prefer': {\n        config.ssl.rejectUnauthorized = false\n        break\n      }\n      case 'require': {\n        if (config.sslrootcert) {\n          // If a root CA is specified, behavior of `sslmode=require` will be the same as that of `verify-ca`\n          config.ssl.checkServerIdentity = function () {}\n        } else {\n          config.ssl.rejectUnauthorized = false","sourceCodeStart":85,"sourceCodeEnd":121,"githubUrl":"https://github.com/brianc/node-postgres/blob/c5e8c9a57bff6d9160ec5dbd5c4f4c1e4c460711/packages/pg-connection-string/index.js#L85-L121","documentation":"Thrown by pg-connection-string's parse() when the caller passes the option { useLibpqCompat: true } AND the connection string itself also contains the query parameter uselibpqcompat=true. The library exposes two ways to opt into libpq-compatible SSL semantics, and having both active simultaneously is treated as a configuration conflict. The guard at index.js:102 explicitly checks options.useLibpqCompat && config.uselibpqcompat and throws so the intent is unambiguous.","triggerScenarios":"Calling parse(connStr, { useLibpqCompat: true }) or new Pool({ connectionString, useLibpqCompat: true }) where connStr already contains '?...&uselibpqcompat=true'. Also triggered via ConnectionParameters when config.useLibpqCompat is set alongside a DATABASE_URL containing uselibpqcompat.","commonSituations":"A team standardizes SSL behavior by adding useLibpqCompat:true to pool config, but the DATABASE_URL env var (often set by a PaaS like Heroku/Render) already includes uselibpqcompat=true. Another case: copy-pasting a working psql/libpq connection string that had uselibpqcompat into code that also sets the programmatic option.","solutions":["Remove uselibpqcompat from the connection string / DATABASE_URL query parameters, keeping only the programmatic { useLibpqCompat: true } option.","Alternatively, remove { useLibpqCompat: true } from your options/config object and rely solely on the connection-string parameter.","Centralize SSL configuration in one place (either the connection string or the options object) and document the chosen approach so contributors do not re-add the other form."],"exampleFix":"// before\nconst pool = new Pool({\n  connectionString: 'postgres://host/db?sslmode=require&uselibpqcompat=true',\n  useLibpqCompat: true,\n});\n\n// after (pick ONE)\nconst pool = new Pool({\n  connectionString: 'postgres://host/db?sslmode=require&uselibpqcompat=true',\n});\n// or\nconst pool = new Pool({\n  connectionString: 'postgres://host/db?sslmode=require',\n  useLibpqCompat: true,\n});","handlingStrategy":"validation","validationCode":"const { parse } = require('pg-connection-string');\n\nfunction safeParse(connStr, options = {}) {\n  // Check the connection string for uselibpqcompat before parsing\n  const hasParam = /[?&]uselibpqcompat=/.test(connStr);\n  if (options.useLibpqCompat && hasParam) {\n    throw new Error(\n      'Conflict: remove uselibpqcompat from the connection string OR remove useLibpqCompat from options.'\n    );\n  }\n  return parse(connStr, options);\n}","typeGuard":null,"tryCatchPattern":"try {\n  const config = parseIntoClientConfig(connStr, { useLibpqCompat: true });\n} catch (err) {\n  if (/useLibpqCompat and uselibpqcompat/i.test(err.message)) {\n    // Strip the duplicate from the connection string and retry without the option\n    const cleaned = connStr.replace(/([?&])uselibpqcompat=[^&]*/i, '$1');\n    config = parseIntoClientConfig(cleaned);\n  } else {\n    throw err;\n  }\n}","preventionTips":["Standardize on exactly one libpq-compat activation method (connection-string param OR options object) and document it in your project README.","Add a startup self-test in CI that validates your production DATABASE_URL against your pool config to catch conflicts before deploy.","When setting useLibpqCompat programmatically, sanitize incoming connection strings by stripping uselibpqcompat."],"tags":["config","connection-string","ssl","validation"],"analyzedSha":"c5e8c9a57bff6d9160ec5dbd5c4f4c1e4c460711","analyzedAt":"2026-08-03T18:47:28.334Z","schemaVersion":2}