{"record":{"id":"2d79cbd3e897f463","repo":"hexojs/hexo","slug":"invalid-config-detected-url-should-be-a-valid-u","errorCode":null,"errorMessage":"Invalid config detected: \"url\" should be a valid URL!","messagePattern":"Invalid config detected: \"url\" should be a valid URL!","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"critical","filePath":"lib/hexo/validate_config.ts","lineNumber":19,"sourceCode":"import assert from 'assert';\nimport moment from 'moment-timezone';\nimport type Hexo from './index';\n\nexport = (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      );","sourceCodeStart":1,"sourceCodeEnd":37,"githubUrl":"https://github.com/hexojs/hexo/blob/059cb17494d0632a053c24077f5bcb6ae92acc51/lib/hexo/validate_config.ts#L1-L37","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"# before\nurl: example.com\n\n# after\nurl: https://example.com","handlingStrategy":"validation","validationCode":"let parsed;\ntry {\n  parsed = new URL(hexo.config.url);\n} catch {\n  throw new Error(`_config.yml 'url' is not a valid URL: ${hexo.config.url}`);\n}\nif (!/^https?:$/.test(parsed.protocol)) {\n  throw new Error(`_config.yml 'url' must use http or https, got ${parsed.protocol}`);\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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."],"tags":["config","validation","startup","url"],"backgroundTag":null,"analyzedSha":"059cb17494d0632a053c24077f5bcb6ae92acc51","analyzedAt":"2026-08-12T20:52:05.731Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}