hexojs/hexo · critical · TypeError
Invalid config detected: "root" should be string, not ${type
Error message
Invalid config detected: "root" should be string, not ${typeof config.root}! What it means
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.
Source
Thrown at lib/hexo/validate_config.ts:23
export = (ctx: Hexo): void => {
const { config, log } = ctx;
log.info('Validating config');
// Validation for config.url && config.root
if (typeof config.url !== 'string') {
throw new TypeError(`Invalid config detected: "url" should be string, not ${typeof config.url}!`);
}
try {
// eslint-disable-next-line no-new
new URL(config.url);
assert(new URL(config.url).protocol.startsWith('http'));
} catch {
throw new TypeError('Invalid config detected: "url" should be a valid URL!');
}
if (typeof config.root !== 'string') {
throw new TypeError(`Invalid config detected: "root" should be string, not ${typeof config.root}!`);
}
if (config.root.trim().length <= 0) {
throw new TypeError('Invalid config detected: "root" should not be empty!');
}
if (!config.timezone) {
log.warn('No timezone setting detected! Using LocalTimeZone as the default timezone.');
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.');
} else {
const configTimezone = moment.tz.zone(config.timezone);
if (!configTimezone) {
log.warn(
`Invalid timezone setting detected! "${config.timezone}" is not a valid timezone.`
);
} else {
const machineTimezone = moment.tz.guess();
if (configTimezone.name !== machineTimezone) {
log.warn(View on GitHub (pinned to 059cb17494)
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.
Example fix
# before root: 0 # after root: /
Defensive patterns
Strategy: validation
Validate before calling
if (typeof hexo.config.root !== 'string') {
throw new Error(`_config.yml 'root' must be a string, got ${typeof hexo.config.root}`);
} Prevention
- Set root: / explicitly in _config.yml.
- Audit plugins that compute/override config.root.
- Lint config types in CI.
When it happens
Trigger: 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).
Common situations: 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.
Related errors
- Invalid config detected: "root" should not be empty!
- Invalid config detected: "url" should be string, not ${typeo
- Invalid config detected: "url" should be a valid URL!
- fn must be a function
- name is required
AI-assisted analysis of hexojs/hexo@059cb17494 (2026-08-12).
Data as JSON: /api/errors/98316aedaa18b6cc.
Report an issue: GitHub.