hexojs/hexo · error · TypeError

path must be a string!

Error message

path must be a string!

What it means

Thrown by the feed_tag helper's makeFeedTag() (lib/plugins/helper/feed_tag.ts:19). The helper builds an RSS/Atom <link> tag. If a path argument is truthy but not a string (number, object, array), it is rejected. A falsy path falls through to the config.feed branch and does not throw.

Source

Thrown at lib/plugins/helper/feed_tag.ts:19

import { url_for } from 'hexo-util';
import moize from 'moize';
import type { LocalsType } from '../../types';

const feedFn = (str = '') => {
  if (str) return str.replace(/2$/, '');
  return str;
};

interface Options {
  title?: string;
  type?: string | null;
}

function makeFeedTag(this: LocalsType, path?: string, options: Options = {}, configFeed?: any, configTitle?: string) {
  const title = options.title || configTitle;

  if (path) {
    if (typeof path !== 'string') throw new TypeError('path must be a string!');

    let type = feedFn(options.type);

    if (!type) {
      if (path.includes('atom')) type = 'atom';
      else if (path.includes('rss')) type = 'rss';
    }

    const typeAttr = type ? `type="application/${type}+xml"` : '';

    return `<link rel="alternate" href="${url_for.call(this, path)}" title="${title}" ${typeAttr}>`;
  }

  if (configFeed) {
    if (configFeed.type && configFeed.path) {
      if (typeof configFeed.type === 'string') {
        return `<link rel="alternate" href="${url_for.call(this, configFeed.path)}" title="${title}" type="application/${feedFn(configFeed.type)}+xml">`;
      }

View on GitHub (pinned to 059cb17494)

Solutions

  1. Pass a string path: <%- feed_tag('atom.xml') %>.
  2. Coerce: <%- feed_tag(String(x)) %> when x may be non-string.
  3. If you have multiple feed paths, loop and call feed_tag once per string.

Example fix

<!-- before -->
<%- feed_tag(feedConfig.path) %>

<!-- after -->
<%- typeof feedConfig.path === 'string' ? feed_tag(feedConfig.path) : '' %>
Defensive patterns

Strategy: type-guard

Validate before calling

if (path != null && typeof path !== 'string') {
  throw new TypeError(`feed_tag path must be a string, got ${typeof path}`);
}
return hexo.extend.helper.get('feed_tag').call(hexo.locals, path);

Type guard

const isFeedPath = (v: unknown): v is string => typeof v === 'string' && v.length > 0;

Prevention

When it happens

Trigger: Calling <%- feed_tag(123) %> or feed_tag(someObject) from a template; passing a parsed URL object; a variable that was expected to be a path string but resolved to a number/object.

Common situations: Theme template passing a config value that is a number or object; refactor of the helper call leaving a non-string; passing an array of paths instead of iterating.

Related errors


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