brianc/node-postgres · error · TypeError

Client was passed a null or undefined query

Error message

Client was passed a null or undefined query

What it means

The native (pg-native-backed) Client.query() throws synchronously as a TypeError when the first argument is null or undefined (native/client.js:165-166). This is an explicit guard before any NativeQuery construction at line 176. Note: passing { text: null } would NOT trigger this — only the first arg itself being null/undefined does.

Source

Thrown at packages/pg/lib/native/client.js:166

// send a query to the server
// this method is highly overloaded to take
// 1) string query, optional array of parameters, optional function callback
// 2) object query with {
//    string query
//    optional array values,
//    optional function callback instead of as a separate parameter
//    optional string name to name & cache the query plan
//    optional string rowMode = 'array' for an array of results
//  }
Client.prototype.query = function (config, values, callback) {
  let query
  let result
  let readTimeout
  let readTimeoutTimer
  let queryCallback

  if (config === null || config === undefined) {
    throw new TypeError('Client was passed a null or undefined query')
  } else if (typeof config.submit === 'function') {
    readTimeout = config.query_timeout || this.connectionParameters.query_timeout
    result = query = config
    // accept query(new Query(...), (err, res) => { }) style
    if (typeof values === 'function') {
      config.callback = values
    }
  } else {
    readTimeout = config.query_timeout || this.connectionParameters.query_timeout
    query = new NativeQuery(config, values, callback)
    if (!query.callback) {
      let resolveOut, rejectOut
      result = new this._Promise((resolve, reject) => {
        resolveOut = resolve
        rejectOut = reject
      }).catch((err) => {
        Error.captureStackTrace(err)
        throw err

View on GitHub (pinned to c5e8c9a57b)

Solutions

  1. Default the query variable before calling: `const sql = buildSql() ?? 'SELECT 1'`.
  2. Guard at the call site: `if (!sql) return`.
  3. Type the parameter as string (not string|undefined) so TypeScript rejects the call at compile time.

Example fix

// before
const sql = maybeBuildQuery(opts) // can return undefined
await client.query(sql)
// after
const sql = maybeBuildQuery(opts)
if (sql === null || sql === undefined) {
  throw new TypeError('query builder returned no SQL')
}
await client.query(sql)
Defensive patterns

Strategy: validation

Validate before calling

const sql = maybeBuildQuery(opts)
if (sql === null || sql === undefined) {
  throw new TypeError('Cannot execute query: SQL config is null/undefined')
}
await client.query(sql)

Type guard

function isQueryableConfig(c): c is string | object {
  return c !== null && c !== undefined
}

if (!isQueryableConfig(config)) {
  throw new TypeError('client.query requires a string or config object')
}
await client.query(config)

Try / catch

try {
  await client.query(maybeSql)
} catch (err) {
  if (err instanceof TypeError && /null or undefined query/.test(err.message)) {
    logger.warn('skipped query: caller passed null/undefined SQL')
    return null
  }
  throw err
}

Prevention

When it happens

Trigger: Calling client.query(null), client.query(undefined), or client.query(someVar) where someVar resolved to null/undefined at runtime. The check at line 165 is a strict === comparison.

Common situations: A SQL builder function returns undefined for an edge case; an optional parameter destructured from a config object that was absent; a refactor that moved the query text out of the call site without a default.

Related errors


AI-assisted analysis of brianc/node-postgres@c5e8c9a57b (2026-08-03). Data as JSON: /data/errors/30d23418be548ab1.json. Report an issue: GitHub.