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

  1. Coerce to string first: router.format(String(x)) or router.format(typeof x === 'string' ? x : '').
  2. If you have a URL object, pass url.pathname (and strip the query, which _format also does).
  3. 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

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.