{"record":{"id":"98316aedaa18b6cc","repo":"hexojs/hexo","slug":"invalid-config-detected-root-should-be-string","errorCode":null,"errorMessage":"Invalid config detected: \"root\" should be string, not ${typeof config.root}!","messagePattern":"Invalid config detected: \"root\" should be string, not (.+?)!","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"critical","filePath":"lib/hexo/validate_config.ts","lineNumber":23,"sourceCode":"export = (ctx: Hexo): void => {\n  const { config, log } = ctx;\n\n  log.info('Validating config');\n\n  // Validation for config.url && config.root\n  if (typeof config.url !== 'string') {\n    throw new TypeError(`Invalid config detected: \"url\" should be string, not ${typeof config.url}!`);\n  }\n  try {\n    // eslint-disable-next-line no-new\n    new URL(config.url);\n    assert(new URL(config.url).protocol.startsWith('http'));\n  } catch {\n    throw new TypeError('Invalid config detected: \"url\" should be a valid URL!');\n  }\n\n  if (typeof config.root !== 'string') {\n    throw new TypeError(`Invalid config detected: \"root\" should be string, not ${typeof config.root}!`);\n  }\n  if (config.root.trim().length <= 0) {\n    throw new TypeError('Invalid config detected: \"root\" should not be empty!');\n  }\n\n  if (!config.timezone) {\n    log.warn('No timezone setting detected! Using LocalTimeZone as the default timezone.');\n    log.warn('This behavior will be changed to UTC in the next major version. Please set timezone explicitly (e.g. LocalTimeZone or America/New_York) in _config.yml to avoid this warning.');\n  } else {\n    const configTimezone = moment.tz.zone(config.timezone);\n    if (!configTimezone) {\n      log.warn(\n        `Invalid timezone setting detected! \"${config.timezone}\" is not a valid timezone.`\n      );\n    } else {\n      const machineTimezone = moment.tz.guess();\n      if (configTimezone.name !== machineTimezone) {\n        log.warn(","sourceCodeStart":5,"sourceCodeEnd":41,"githubUrl":"https://github.com/hexojs/hexo/blob/059cb17494d0632a053c24077f5bcb6ae92acc51/lib/hexo/validate_config.ts#L5-L41","documentation":"Thrown by validate_config (lib/hexo/validate_config.ts:23). config.root (the path under which the site is served) must be a string. It is checked after url, so url already passed.","triggerScenarios":"config.root is a number, object, array, or null/undefined in _config.yml (e.g. root: 0, root: [/], root omitted and defaulted to a non-string).","commonSituations":"YAML parsing a bare token into a non-string; a theme/plugin overriding root with a non-string; deleting the root line expecting a default but a plugin set it to undefined; config merge producing a non-string.","solutions":["Set root to a string path in _config.yml, typically root: /.","If root is computed by a plugin, ensure it returns a string.","Search for assignments to config.root and fix non-string producers."],"exampleFix":"# before\nroot: 0\n\n# after\nroot: /","handlingStrategy":"validation","validationCode":"if (typeof hexo.config.root !== 'string') {\n  throw new Error(`_config.yml 'root' must be a string, got ${typeof hexo.config.root}`);\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Set root: / explicitly in _config.yml.","Audit plugins that compute/override config.root.","Lint config types in CI."],"tags":["config","validation","startup","root"],"backgroundTag":null,"analyzedSha":"059cb17494d0632a053c24077f5bcb6ae92acc51","analyzedAt":"2026-08-12T20:52:05.731Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}