{"record":{"id":"335cd5207667117b","repo":"videojs/video.js","slug":"lvl-in-not-a-valid-log-level","errorCode":null,"errorMessage":"\"${lvl}\" in not a valid log level","messagePattern":"\"(.+?)\" in not a valid log level","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/js/utils/create-logger.js","lineNumber":198,"sourceCode":"    DEFAULT: level\n  };\n\n  /**\n   * Get or set the current logging level.\n   *\n   * If a string matching a key from {@link module:log.levels} is provided, acts\n   * as a setter.\n   *\n   * @param  {'all'|'debug'|'info'|'warn'|'error'|'off'} [lvl]\n   *         Pass a valid level to set a new logging level.\n   *\n   * @return {string}\n   *         The current logging level.\n   */\n  log.level = (lvl) => {\n    if (typeof lvl === 'string') {\n      if (!log.levels.hasOwnProperty(lvl)) {\n        throw new Error(`\"${lvl}\" in not a valid log level`);\n      }\n      level = lvl;\n    }\n    return level;\n  };\n\n  /**\n   * Returns an array containing everything that has been logged to the history.\n   *\n   * This array is a shallow clone of the internal history record. However, its\n   * contents are _not_ cloned; so, mutating objects inside this array will\n   * mutate them in history.\n   *\n   * @return {Array}\n   */\n  log.history = () => history ? [].concat(history) : [];\n\n  /**","sourceCodeStart":180,"sourceCodeEnd":216,"githubUrl":"https://github.com/videojs/video.js/blob/c3a7e0e6d20cf5400c9afbee29965fe4dff393c2/src/js/utils/create-logger.js#L180-L216","documentation":"Thrown by log.level(lvl) when lvl is a string that is not a key of log.levels. Valid level keys are 'all', 'off', 'debug', 'info', 'warn', 'error' (plus the meta 'DEFAULT'). Passing undefined (or any non-string) acts as a getter and does not throw. Note the message has a typo ('in not' instead of 'is not').","triggerScenarios":"Calling videojs.log.level('trace'), videojs.log.level('verbose'), or videojs.log.level('fatal') - any string outside the allowed set. Common when the level comes from an env var or config without validation.","commonSituations":"Migrating from another logger (winston, loglevel, pino) whose level names differ; reading the level from a QUERY_STRING/ENV/config file that uses 'trace'/'verbose'/'silent'; case-sensitivity issues ('Error' vs 'error').","solutions":["Use one of the allowed levels: 'all', 'off', 'debug', 'info', 'warn', 'error'.","Validate an env/config-derived level against Object.keys(videojs.log.levels) before setting.","Lowercase the input and fall back to a sane default if unknown."],"exampleFix":"// before\nvideojs.log.level('trace');\n// after\nvideojs.log.level('debug');","handlingStrategy":"validation","validationCode":"const ALLOWED = Object.keys(videojs.log.levels);\nfunction safeSetLevel(lvl) {\n  const norm = String(lvl).toLowerCase();\n  if (!ALLOWED.includes(norm)) {\n    throw new TypeError(`log level must be one of ${ALLOWED.join(', ')}, got: ${lvl}`);\n  }\n  return videojs.log.level(norm);\n}","typeGuard":"function isValidLogLevel(lvl) {\n  return typeof lvl === 'string' && Object.prototype.hasOwnProperty.call(videojs.log.levels, lvl.toLowerCase());\n}","tryCatchPattern":"try {\n  videojs.log.level(lvl);\n} catch (err) {\n  if (/valid log level/.test(err.message)) {\n    videojs.log.level('info');\n  } else { throw err; }\n}","preventionTips":["Lowercase and validate config/env-derived levels against Object.keys(videojs.log.levels).","Map foreign level names (trace->debug, fatal->error, verbose->debug) before setting.","Treat undefined as a getter, not a setter, to avoid accidental throws."],"tags":["logging","validation","config"],"backgroundTag":null,"analyzedSha":"c3a7e0e6d20cf5400c9afbee29965fe4dff393c2","analyzedAt":"2026-08-13T04:20:15.471Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}