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

  1. Prefix the scheme: url: https://example.com.
  2. Remove any protocol-relative form (//example.com) and use https://.
  3. Trim stray whitespace/quotes around the value in _config.yml.
  4. 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

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


AI-assisted analysis of hexojs/hexo@059cb17494 (2026-08-12). Data as JSON: /api/errors/2d79cbd3e897f463. Report an issue: GitHub.