pinojs/pino · error · Error
Levels comparison should be one of "ASC", "DESC" or "functio
Error message
Levels comparison should be one of "ASC", "DESC" or "function" type
What it means
pino's assertLevelComparison validates the levelComparison option used for sorting custom levels. It must be the string "ASC", "DESC", or a function; anything else (other strings, numbers, etc.) is rejected at logger creation time.
Source
Thrown at lib/levels.js:226
}
/**
* Validates whether `levelComparison` is correct
*
* @throws Error
* @param {SORTING_ORDER | Function} levelComparison - value to validate
* @returns
*/
function assertLevelComparison (levelComparison) {
if (typeof levelComparison === 'function') {
return
}
if (typeof levelComparison === 'string' && Object.values(SORTING_ORDER).includes(levelComparison)) {
return
}
throw new Error('Levels comparison should be one of "ASC", "DESC" or "function" type')
}
module.exports = {
initialLsCache,
genLsCache,
levelMethods,
getLevel,
setLevel,
isLevelEnabled,
mappings,
assertNoLevelCollisions,
assertDefaultLevelFound,
genLevelComparison,
assertLevelComparison
}
View on GitHub (pinned to 5aa62305c5)
Solutions
- Use the exact strings "ASC" or "DESC" (uppercase)
- Pass a comparator function: levelComparison: (a, b) => a - b
- Normalize config values: levelComparison: (raw || '').toUpperCase()
Example fix
// before
pino({ customLevels: { foo: 30 }, levelComparison: 'asc' });
// after
pino({ customLevels: { foo: 30 }, levelComparison: 'ASC' }); Defensive patterns
Strategy: validation
Validate before calling
const VALID = ['ASC', 'DESC'];
function assertLevelComparison(lc) {
if (!(VALID.includes(lc) || typeof lc === 'function')) {
throw new TypeError('levelComparison must be "ASC", "DESC", or a function');
}
} Type guard
function isValidLevelComparison(v) { return v === 'ASC' || v === 'DESC' || typeof v === 'function'; } Try / catch
try { const logger = pino(opts); } catch (e) { if (/Levels comparison/.test(e.message)) { opts.levelComparison = 'ASC'; } throw e; } Prevention
- Normalize case when levelComparison comes from config: String(raw).toUpperCase()
- Use TypeScript union type: 'ASC' | 'DESC' | ((a: number, b: number) => number)
- Only pass levelComparison when configuring custom levels
When it happens
Trigger: Passing pino({ levelComparison: 'asc' }) (lowercase), levelComparison: true, levelComparison: 1, or any value not in SORTING_ORDER and not a function.
Common situations: Typos or wrong casing when configuring custom levels sort order; passing a comparison value read from config that is not normalized; misunderstanding that only exact "ASC"/"DESC" strings are accepted.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- unknown level ${level}
- unknown level value${level}
- customLevels is required if useOnlyCustomLevels is set true
- missing bindings for child Pino
- prettyPrint option is no longer supported, see the pino-pret
AI-assisted analysis of pinojs/pino@5aa62305c5 (2026-09-02).
Data as JSON: /api/errors/b4468643c2b0ff8b.
Report an issue: GitHub.