pinojs/pino · error · Error
Unknown mixin type "${typeof mixin}" - expected "function"
Error message
Unknown mixin type "${typeof mixin}" - expected "function" What it means
The mixin option must be a function that returns an object merged into each log line. If opts.mixin is truthy but not a function, Pino throws with the actual typeof found. This fails fast at logger creation rather than per-log-call.
Source
Thrown at pino.js:165
[formattersSym]: allFormatters
})
let chindings = ''
if (base !== null) {
if (name === undefined) {
chindings = coreChindings(base)
} else {
chindings = coreChindings(Object.assign({}, base, { name }))
}
}
const time = (timestamp instanceof Function)
? timestamp
: (timestamp ? epochTime : nullTime)
const timeSliceIndex = time().indexOf(':') + 1
if (useOnlyCustomLevels && !customLevels) throw Error('customLevels is required if useOnlyCustomLevels is set true')
if (mixin && typeof mixin !== 'function') throw Error(`Unknown mixin type "${typeof mixin}" - expected "function"`)
if (msgPrefix && typeof msgPrefix !== 'string') throw Error(`Unknown msgPrefix type "${typeof msgPrefix}" - expected "string"`)
assertDefaultLevelFound(level, customLevels, useOnlyCustomLevels)
const levels = mappings(customLevels, useOnlyCustomLevels)
if (stream && stream[transportUsesMultistreamSym] === true) {
let sampleLabel = typeof level === 'string' ? level : undefined
if (!sampleLabel || levels[sampleLabel] === undefined) {
sampleLabel = Object.keys(levels)[0]
}
const sampleNumber = levels[sampleLabel]
let ok = false
try {
const formatted = formatters.level(sampleLabel, sampleNumber)
ok = formatted && typeof formatted === 'object' && formatted.level === sampleNumber
} catch {
ok = false
}View on GitHub (pinned to 5aa62305c5)
Solutions
- Pass a function: mixin: () => ({ ... }) or mixin: (context) => ({ ...context }).
- If the mixin is generated, pass the factory's returned function, not an intermediate object.
- If options come from config files, re-attach functions in code after loading the config.
- Check typeof opts.mixin === 'function' before calling pino in wrapper code.
Example fix
// before
const logger = pino({ mixin: { requestId: 'abc' } })
// after
const logger = pino({ mixin: () => ({ requestId: 'abc' }) }) Defensive patterns
Strategy: type-guard
Validate before calling
function validateMixin(opts) {
if (opts && opts.mixin && typeof opts.mixin !== 'function') {
throw new TypeError(`mixin must be a function, got ${typeof opts.mixin}`)
}
return true
} Type guard
const isMixinFn = (opts) => !opts.mixin || typeof opts.mixin === 'function'
Try / catch
try {
const logger = pino(opts)
} catch (err) {
if (err.message.startsWith('Unknown mixin type')) {
logger = pino({ ...opts, mixin: undefined }) // or wrap: mixin: () => opts.mixin
} else throw err
} Prevention
- Never call the mixin when assigning it: mixin: myMixin, not mixin: myMixin()
- Re-hydrate function options after loading config from JSON/YAML files
- Type-check options in wrappers: assert typeof opts.mixin === 'function'
When it happens
Trigger: pino({ mixin: someObject }) or mixin set to a string/number/boolean; passing the result of calling the mixin (mixin: myMixin()) instead of the function itself; config deserialized from JSON where functions can't survive.
Common situations: Loading logger options from JSON/YAML config files (functions lost); wrapping mistakes like mixin: mixinFactory() returning an object; typos assigning an object where a callback is expected.
Related errors
- Unknown msgPrefix type "${typeof msgPrefix}" - expected "str
- Levels comparison should be one of "ASC", "DESC" or "functio
- only one of option.transport or stream can be specified
- option.transport do not allow stream, please pass to option
- option.transport.targets do not allow custom level formatter
AI-assisted analysis of pinojs/pino@5aa62305c5 (2026-09-02).
Data as JSON: /api/errors/738349e4ddff610c.
Report an issue: GitHub.