pinojs/pino · error · Error
prettyPrint option is no longer supported, see the pino-pret
Error message
prettyPrint option is no longer supported, see the pino-pretty package (https://github.com/pinojs/pino-pretty)
What it means
The prettyPrint option was removed in pino v7+. createArgsNormalizer (lib/tools.js:356) rejects it outright and directs users to the standalone pino-pretty package, because pretty-printing is now handled as a transport rather than an in-process option.
Source
Thrown at lib/tools.js:356
if (opts.transport instanceof SonicBoom || opts.transport.writable || opts.transport._writableState) {
throw Error('option.transport do not allow stream, please pass to option directly. e.g. pino(transport)')
}
if (opts.transport.targets && opts.transport.targets.length && opts.formatters && typeof opts.formatters.level === 'function') {
throw Error('option.transport.targets do not allow custom level formatters')
}
let customLevels
if (opts.customLevels) {
customLevels = opts.useOnlyCustomLevels ? opts.customLevels : Object.assign({}, opts.levels, opts.customLevels)
}
stream = transport({ caller, ...opts.transport, levels: customLevels })
}
opts = Object.assign({}, defaultOptions, opts)
opts.serializers = Object.assign(Object.create(null), defaultOptions.serializers, opts.serializers)
opts.formatters = Object.assign({}, defaultOptions.formatters, opts.formatters)
if (opts.prettyPrint) {
throw new Error('prettyPrint option is no longer supported, see the pino-pretty package (https://github.com/pinojs/pino-pretty)')
}
const { enabled, onChild } = opts
if (enabled === false) opts.level = 'silent'
if (!onChild) opts.onChild = noop
if (!stream) {
if (!hasBeenTampered(process.stdout)) {
// If process.stdout.fd is undefined, it means that we are running
// in a worker thread. Let's assume we are logging to file descriptor 1.
stream = buildSafeSonicBoom({ fd: process.stdout.fd || 1 })
} else {
stream = process.stdout
}
}
return { opts, stream }
}
}
View on GitHub (pinned to 5aa62305c5)
Solutions
- Remove the prettyPrint option and use a transport: pino({ transport: { target: 'pino-pretty' } })
- Pipe output through the pino-pretty CLI: node app.js | pino-pretty
- Pin pino v6 only if you cannot migrate (not recommended)
Example fix
// before
const logger = pino({ prettyPrint: { colorize: true } });
// after
const logger = pino({ transport: { target: 'pino-pretty', options: { colorize: true } } }); Defensive patterns
Strategy: validation
Validate before calling
function assertNoPrettyPrint(opts = {}) {
if ('prettyPrint' in opts) {
throw new Error('prettyPrint was removed in pino v7; use transport with pino-pretty');
}
} Type guard
function usesLegacyPrettyPrint(opts) { return typeof opts === 'object' && opts !== null && 'prettyPrint' in opts; } Try / catch
try { logger = pino(opts); } catch (e) { if (/prettyPrint option is no longer supported/.test(e.message)) { logger = pino({ transport: { target: 'pino-pretty' } }); } else { throw e; } } Prevention
- Audit options objects when upgrading pino major versions
- Use pino-pretty as a transport target or CLI pipe instead
- Centralize logger construction in one module so deprecated options are removed in one place
When it happens
Trigger: Passing pino({ prettyPrint: true }) or any truthy prettyPrint object to pino() or pino.destination().
Common situations: Upgrading from pino v6 or earlier to v7+; copying old tutorials or config; enabling pretty logs in production code that was written against the legacy API.
Related errors
- missing bindings for child Pino
- Levels comparison should be one of "ASC", "DESC" or "functio
- only one of target or targets can be specified
- unable to determine transport target for "${origin}"
- PINO_TRANSPORT_MULTI_TARGETS_LEVEL_FORMATTER
AI-assisted analysis of pinojs/pino@5aa62305c5 (2026-09-02).
Data as JSON: /api/errors/35afede962fec4b7.
Report an issue: GitHub.