pinojs/pino · error · Error

missing bindings for child Pino

Error message

missing bindings for child Pino

What it means

pino().child() requires a bindings object as its first argument. The browser build's child function (browser.js:208) throws immediately when bindings is falsy because a child logger must inherit at least an empty set of bindings to derive its identity.

Source

Thrown at browser.js:208

      throw Error('unknown level ' + level)
    }
    this._level = level

    set(this, setOpts, logger, 'error') // <-- must stay first
    set(this, setOpts, logger, 'fatal')
    set(this, setOpts, logger, 'warn')
    set(this, setOpts, logger, 'info')
    set(this, setOpts, logger, 'debug')
    set(this, setOpts, logger, 'trace')

    customLevels.forEach((level) => {
      set(this, setOpts, logger, level)
    })
  }

  function child (setOpts, bindings, childOptions) {
    if (!bindings) {
      throw new Error('missing bindings for child Pino')
    }
    childOptions = childOptions || {}
    if (serialize && bindings.serializers) {
      childOptions.serializers = bindings.serializers
    }
    const childOptionsSerializers = childOptions.serializers
    if (serialize && childOptionsSerializers) {
      var childSerializers = Object.assign({}, serializers, childOptionsSerializers)
      var childSerialize = opts.browser.serialize === true
        ? Object.keys(childSerializers)
        : serialize
      delete bindings.serializers
      applySerializers([bindings], childSerialize, childSerializers, this._stdErrSerialize)
    }
    function Child (parent) {
      this._childLevel = (parent._childLevel | 0) + 1

      // make sure bindings are available in the `set` function

View on GitHub (pinned to 5aa62305c5)

Solutions

  1. Pass a bindings object as the first argument, even if empty: logger.child({})
  2. Move any contextual fields (requestId, module name) into the bindings object
  3. If you intended to pass only childOptions, pass bindings first: logger.child({}, childOptions)

Example fix

// before
const child = logger.child();
// after
const child = logger.child({ module: 'payments' });
Defensive patterns

Strategy: validation

Validate before calling

function safeChild(logger, bindings) {
  if (bindings == null || typeof bindings !== 'object') {
    throw new TypeError('child() requires a bindings object');
  }
  return logger.child(bindings);
}

Type guard

function hasBindings(b) { return typeof b === 'object' && b !== null; }

Try / catch

try { const child = logger.child(bindings); } catch (e) { if (e.message === 'missing bindings for child Pino') { child = logger.child({}); } else { throw e; } }

Prevention

When it happens

Trigger: Calling logger.child() with no arguments, or explicitly with undefined/null as the first argument, e.g. logger.child().

Common situations: Migrating from other logging libraries (like winston's child or custom factories) that allow argument-less child(); refactoring code that removed bindings but left the child() call; forgetting to pass { reqId } style context.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


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