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

  1. Pass a function: logger.flush(() => { ... }) or omit the argument entirely (logger.flush()).
  2. If you need completion semantics without a callback, pass a function that resolves your promise.
  3. Check the call site for accidentally forwarded non-function arguments.
  4. 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

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


AI-assisted analysis of pinojs/pino@5aa62305c5 (2026-09-02). Data as JSON: /api/errors/96ba33dd0392b3a0. Report an issue: GitHub.