hexojs/hexo · error · TypeError
path must be a string!
Error message
path must be a string!
What it means
Thrown by the internal _format() helper in lib/hexo/router.ts:83. _format normalizes a route path (strips leading slashes, flips backslashes, drops query strings, appends index.html). It first does path = path || '' so null/undefined are coerced to '' (no throw); the throw fires only for truthy non-string values.
Source
Thrown at lib/hexo/router.ts:83
this.emit('error', err);
});
} else {
const bufferData = this._toBuffer(data);
if (bufferData) {
this.push(bufferData);
}
this.push(null);
}
}).catch(err => {
this.emit('error', err);
this.push(null);
});
}
}
const _format = (path?: string): string => {
path = path || '';
if (typeof path !== 'string') throw new TypeError('path must be a string!');
path = path
.replace(/^\/+/, '') // Remove prefixed slashes
.replace(/\\/g, '/') // Replaces all backslashes
.replace(/\?.*$/, ''); // Remove query string
// Appends `index.html` to the path with trailing slash
if (!path || path.endsWith('/')) {
path += 'index.html';
}
return path;
};
class Router extends EventEmitter {
public routes: {
[key: string]: Data | null;
};View on GitHub (pinned to 059cb17494)
Solutions
- Coerce to string first: router.format(String(x)) or router.format(typeof x === 'string' ? x : '').
- If you have a URL object, pass url.pathname (and strip the query, which _format also does).
- Type-check at the call site before invoking format().
Example fix
// before router.format(parsedUrl); // parsedUrl is a URL object // after router.format(parsedUrl.pathname);
Defensive patterns
Strategy: type-guard
Validate before calling
if (path != null && typeof path !== 'string') {
throw new TypeError(`router.format expects a string, got ${typeof path}`);
}
return hexo.route.format(path); Type guard
const isRoutePath = (v: unknown): v is string => typeof v === 'string';
Prevention
- Pass url.pathname from URL objects, not the URL object itself.
- Coerce with String() when the value is numeric.
- Keep route paths in string-typed collections.
When it happens
Trigger: Calling router.format(123), router.format(true), router.format({}), router.format([]), or router.format(()=>{}). These reach _format via the public format() method (line 114-116).
Common situations: Passing a parsed URL object (new URL(...)) instead of url.pathname; passing a number index; a template/helper that interpolates a non-string variable into a route.format call.
Related errors
AI-assisted analysis of hexojs/hexo@059cb17494 (2026-08-12).
Data as JSON: /api/errors/f3858f34fcab973a.
Report an issue: GitHub.