brianc/node-postgres · error · TypeError

callback is not a function

Error message

callback is not a function

What it means

Thrown synchronously (as a TypeError) by Client.prototype.query when a Query is constructed with a callback value that is truthy but not a function. In client.js:645-657, after new Query(config, values, callback), if query.callback is truthy but typeof query.callback !== 'function', the library rejects it. This happens when the third positional argument to query(), or config.callback on a config object, is a non-function truthy value (number, string, object). The library refuses to silently accept a broken callback because every code path that uses query.callback calls it.

Source

Thrown at packages/pg/lib/client.js:656

        if (typeof values === 'function') {
          query.callback = values
        } else if (callback) {
          query.callback = callback
        }
      }
    } else {
      query = new Query(config, values, callback)
      if (!query.callback) {
        result = new this._Promise((resolve, reject) => {
          query.callback = (err, res) => (err ? reject(err) : resolve(res))
        }).catch((err) => {
          // replace the stack trace that leads to `TCP.onStreamRead` with one that leads back to the
          // application that created the query
          Error.captureStackTrace(err)
          throw err
        })
      } else if (typeof query.callback !== 'function') {
        throw new TypeError('callback is not a function')
      }
    }

    const readTimeout = config.query_timeout || this.connectionParameters.query_timeout
    if (readTimeout) {
      const queryCallback = query.callback || (() => {})

      const readTimeoutTimer = setTimeout(() => {
        const error = new Error('Query read timeout')

        process.nextTick(() => {
          query.handleError(error, this.connection)
        })

        queryCallback(error)

        // we already returned an error,
        // just do nothing if query completes

View on GitHub (pinned to c5e8c9a57b)

Solutions

  1. Ensure the third argument to client.query(text, values, callback) is a function or omitted.
  2. If using a config object, ensure config.callback is a function or remove it to use the returned promise instead.
  3. Switch to async/await with client.query(text, values) and drop the callback argument entirely.

Example fix

// before
client.query('SELECT $1', cb, [1]); // wrong argument order

// after
client.query('SELECT $1', [1], cb); // (text, values, callback)
// or
const res = await client.query('SELECT $1', [1]);
Defensive patterns

Strategy: type-guard

Validate before calling

function isFunction(v) {
  return typeof v === 'function';
}

// before calling:
if (callback !== undefined && !isFunction(callback)) {
  throw new TypeError('callback must be a function');
}
client.query(text, values, callback);

Type guard

function isValidCallback(cb) {
  return cb === undefined || typeof cb === 'function';
}

// usage:
if (isValidCallback(cb)) {
  client.query(text, values, cb);
}

Try / catch

try {
  client.query(text, values, callback);
} catch (err) {
  if (err instanceof TypeError && /callback is not a function/i.test(err.message)) {
    // drop the bad callback and use the promise instead
    return client.query(text, values);
  }
  throw err;
}

Prevention

When it happens

Trigger: client.query('SELECT 1', [], 'notafunc'), client.query({ text: 'SELECT 1', callback: 42 }), or passing a value where the third arg is an object instead of a function. normalizeQueryConfig (utils.js:154-155) assigns any truthy callback directly to config.callback without type-checking, so the guard in client.js catches it.

Common situations: Passing values array in the wrong position (e.g., client.query(text, callback, values) instead of client.query(text, values, callback)). A config object with a stale callback property left over from refactoring. Misunderstanding the overload signatures of client.query.

Related errors


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