pinojs/pino · error · Error
callback must be a function
Error message
callback must be a function
What it means
flush(cb) accepts an optional callback but strictly rejects any non-function, non-nullish argument. The callback is invoked once the underlying stream has been flushed, so pino validates its type up front to avoid a confusing async TypeError later.
Source
Thrown at lib/proto.js:248
obj = mixinMergeStrategy(obj, mixin(obj, num, this))
}
const s = this[asJsonSym](obj, msg, num, t)
const stream = this[streamSym]
if (stream[needsMetadataGsym] === true) {
stream.lastLevel = num
stream.lastObj = obj
stream.lastMsg = msg
stream.lastTime = t.slice(this[timeSliceIndexSym])
stream.lastLogger = this // for child loggers
}
stream.write(streamWriteHook ? streamWriteHook(s) : s)
}
function flush (cb) {
if (cb != null && typeof cb !== 'function') {
throw Error('callback must be a function')
}
const stream = this[streamSym]
if (typeof stream.flush === 'function') {
stream.flush(cb || noop)
} else if (cb) cb()
}
View on GitHub (pinned to 5aa62305c5)
Solutions
- Pass a function: logger.flush(() => { ... }) or omit the argument entirely (logger.flush()).
- If you need completion semantics without a callback, pass a function that resolves your promise.
- Check the call site for accidentally forwarded non-function arguments.
- Note flush(cb != null) — only null/undefined are allowed as 'no callback'; use those, not false.
Example fix
// before
logger.flush(true)
// after
logger.flush((err) => { if (err) console.error(err) }) Defensive patterns
Strategy: type-guard
Validate before calling
function safeFlush(logger, cb) {
if (cb != null && typeof cb !== 'function') {
throw new TypeError('flush expects a function callback or nothing')
}
logger.flush(cb || undefined)
} Type guard
function isFlushCallback(cb) {
return cb == null || typeof cb === 'function'
} Try / catch
try {
logger.flush(onFlushed)
} catch (e) {
if (e.message === 'callback must be a function') {
logger.flush() // proceed without callback
} else throw e
} Prevention
- Call flush() with either nothing or an explicit function.
- Wrap promise-style usage: logger.flush(() => resolve()).
- Never forward arbitrary arguments (options/streams) into flush().
- Guard callbacks that may be undefined: flush(cb || undefined).
When it happens
Trigger: logger.flush('cb'); logger.flush(true); passing something truthy but not callable, e.g. flush(options) or flush(stream) by mistake.
Common situations: Confusing flush with an options-taking API; passing a promise resolver incorrectly or a renamed variable that no longer holds a function.
Related errors
- missing bindings for child Pino
- only one of target or targets can be specified
- unknown level ${level}
- levelVal is read-only
- missing bindings for child Pino
AI-assisted analysis of pinojs/pino@5aa62305c5 (2026-09-02).
Data as JSON: /api/errors/96ba33dd0392b3a0.
Report an issue: GitHub.