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 completesView on GitHub (pinned to c5e8c9a57b)
Solutions
- Ensure the third argument to client.query(text, values, callback) is a function or omitted.
- If using a config object, ensure config.callback is a function or remove it to use the returned promise instead.
- 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
- Use async/await and drop positional callback arguments entirely.
- Memorize the overload order: client.query(text, values, callback) — callback is always third.
- Never set config.callback to a non-function; if migrating to promises, remove the callback property.
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
- Client was passed a null or undefined query
- Client was passed a null or undefined query
- Both useLibpqCompat and uselibpqcompat are set. Please use o
- Invalid ${key}: ${value}
- Invalid sslnegotiation value: "${this.sslnegotiation}". Vali
AI-assisted analysis of brianc/node-postgres@c5e8c9a57b (2026-08-03).
Data as JSON: /data/errors/8f6ca339dfa3eb90.json.
Report an issue: GitHub.