pinojs/pino · error · Error
unknown level ${level}
Error message
unknown level ${level} What it means
The browser logger's setLevel (browser.js:190) throws when assigned a level that is not 'silent' and has no entry in logger.levels.values. Only levels registered on the logger instance (default or custom) are accepted.
Source
Thrown at browser.js:190
this._logEvent.bindings.push(newBindings)
}
// reassigning the level rebuilds the log functions so the updated
// bindings are prepended to subsequent log calls
this.level = this._level
}
if (transmit) logger._logEvent = createLogEventShape()
function getLevelVal () {
return levelToValue(this.level, this)
}
function getLevel () {
return this._level
}
function setLevel (level) {
if (level !== 'silent' && !this.levels.values[level]) {
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')View on GitHub (pinned to 5aa62305c5)
Solutions
- Use a valid pino level: trace, debug, info, warn, error, fatal, or silent
- Register custom levels: pino({ customLevels: { verbose: 25 } })
- Trim/normalize the level string before assigning: level.trim().toLowerCase()
Example fix
// before
logger.level = 'verbose';
// after
const logger = pino({ customLevels: { verbose: 25 } });
logger.level = 'verbose'; Defensive patterns
Strategy: validation
Validate before calling
function safeSetLevel(logger, level) {
const l = String(level).trim().toLowerCase();
if (l !== 'silent' && !(l in logger.levels.values)) {
throw new Error(`unknown level: ${level}`);
}
logger.level = l;
} Type guard
function isKnownLevel(logger, level) {
return level === 'silent' || typeof logger.levels.values[level] === 'number';
} Try / catch
try { logger.level = cfgLevel; } catch (e) { if (/unknown level/.test(e.message)) { logger.level = 'info'; console.warn(e.message); } else { throw e; } } Prevention
- Validate levels from config/env against logger.levels.values before assigning
- Normalize casing/whitespace: level.trim().toLowerCase()
- If using non-standard level names, define them via customLevels
When it happens
Trigger: logger.level = 'verbose' or logger.setLevel('trace ') (trailing space) where 'verbose' isn't a registered pino level and no customLevels define it.
Common situations: Using level names from other logging libraries (winston's 'verbose'/'silly'); typos or casing issues ('TRACE'); reading the level from user config or env without validating against known levels.
Related errors
- pino – redact must contain an array of strings
- pino: transmit option must have a send function
- unknown level value${level}
- missing bindings for child Pino
- Levels comparison should be one of "ASC", "DESC" or "functio
AI-assisted analysis of pinojs/pino@5aa62305c5 (2026-09-02).
Data as JSON: /api/errors/37630a5d7fafb1a3.
Report an issue: GitHub.