nodejs/node · error · Error

Query params cannot be passed when url already contains "?"

Error message

Query params cannot be passed when url already contains "?" or "#".

What it means

serializePathWithQuery throws when the input URL string already contains '?' or '#', because appending another serialized query would produce a malformed URL (duplicate '?' or query after fragment). Undici treats this as a programmer error rather than silently merging.

Source

Thrown at deps/undici/src/lib/core/util.js:109

/**
 * @param {string} url The path to check for query strings or fragments.
 * @returns {boolean} Returns true if the path contains a query string or fragment.
 */
function pathHasQueryOrFragment (url) {
  return (
    url.includes('?') ||
    url.includes('#')
  )
}

/**
 * @param {string} url The URL to add the query params to
 * @param {import('node:querystring').ParsedUrlQueryInput} queryParams The object to serialize into a URL query string
 * @returns {string} The URL with the query params added
 */
function serializePathWithQuery (url, queryParams) {
  if (pathHasQueryOrFragment(url)) {
    throw new Error('Query params cannot be passed when url already contains "?" or "#".')
  }

  const stringified = stringify(queryParams)

  if (stringified) {
    url += '?' + stringified
  }

  return url
}

/**
 * @param {number|string|undefined} port
 * @returns {boolean}
 */
function isValidPort (port) {
  const value = parseInt(port, 10)
  return (

View on GitHub (pinned to 1b2de5e052)

Solutions

  1. Drop the query string from the URL and supply all params via queryParams.
  2. Or drop queryParams and pre-serialize with new URLSearchParams(...).toString() into the URL.
  3. Use the URL/URLSearchParams APIs to mutate the URL in place rather than concatenating strings.

Example fix

// before
client.request('https://api.example/x?a=1', { query: { b: 2 } })
// after
client.request('https://api.example/x', { query: { a: 1, b: 2 } })
Defensive patterns

Strategy: validation

Validate before calling

function buildUrl(base, query) {
  if (query && (base.includes('?') || base.includes('#'))) {
    throw new Error('Cannot combine inline query with queryParams object')
  }
  // proceed with the API call
  return query ? `${base}?${new URLSearchParams(query).toString()}` : base
}

Prevention

When it happens

Trigger: Passing both a URL with embedded query/fragment AND a queryParams object to an internal helper that calls serializePathWithQuery (the public fetch/request APIs do not surface this directly; it fires through diagnostic, interceptor, or ProxyAgent path-building code).

Common situations: Hand-building URLs with template strings then also passing { query: {...} }; migrating from got/axios where query merging was lenient; double-encoding after a redirect handler that re-applies params.

Related errors


AI-assisted analysis of nodejs/node@1b2de5e052 (2026-08-13). Data as JSON: /api/errors/d0101e1cb1b37fb5. Report an issue: GitHub.