hexojs/hexo · critical · TypeError
Invalid config detected: "url" should be a valid URL!
Error message
Invalid config detected: "url" should be a valid URL!
What it means
Thrown by validate_config (lib/hexo/validate_config.ts:19). config.url is a string but either new URL(config.url) throws (malformed) or its protocol does not start with 'http' (e.g. ftp:, file:, mailto:, javascript:). Only http/https URLs are accepted.
Source
Thrown at lib/hexo/validate_config.ts:19
import assert from 'assert';
import moment from 'moment-timezone';
import type Hexo from './index';
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.`
);View on GitHub (pinned to 059cb17494)
Solutions
- Prefix the scheme: url: https://example.com.
- Remove any protocol-relative form (//example.com) and use https://.
- Trim stray whitespace/quotes around the value in _config.yml.
- Ensure the URL uses only http or https; other protocols are rejected.
Example fix
# before url: example.com # after url: https://example.com
Defensive patterns
Strategy: validation
Validate before calling
let parsed;
try {
parsed = new URL(hexo.config.url);
} catch {
throw new Error(`_config.yml 'url' is not a valid URL: ${hexo.config.url}`);
}
if (!/^https?:$/.test(parsed.protocol)) {
throw new Error(`_config.yml 'url' must use http or https, got ${parsed.protocol}`);
} Prevention
- Always include the scheme (https://).
- Add a pre-flight check in CI: node -e "new URL(require('./_config.yml').url)".
- Reject protocol-relative URLs in config reviews.
When it happens
Trigger: url: example.com (missing scheme — new URL may throw or yield an unexpected protocol depending on input); url: ftp://x; url: //cdn.example.com; url with a typo like htpp://; url: mailto:foo@bar.com; CNAME-style bare domain.
Common situations: Forgetting the http:// or https:// scheme (most common); using a protocol-relative URL; pasting an email or ftp link; trailing/leading whitespace in the YAML value that breaks parsing.
Related errors
- Invalid config detected: "url" should be string, not ${typeo
- Invalid config detected: "root" should be string, not ${type
- Invalid config detected: "root" should not be empty!
- fn must be a function
- name is required
AI-assisted analysis of hexojs/hexo@059cb17494 (2026-08-12).
Data as JSON: /api/errors/2d79cbd3e897f463.
Report an issue: GitHub.