hexojs/hexo · error · Error

Partial ${name} does not exist. (in ${currentView})

Error message

Partial ${name} does not exist. (in ${currentView})

What it means

Hexo's `partial` helper renders a sub-template from the active theme's view registry. It resolves `name` first relative to the current view's directory (`join(dirname(currentView), name)`), then falls back to the bare `name`, both via `ctx.theme.getView()`. If neither lookup returns a registered view, Hexo throws — it cannot render a partial it cannot find in the theme. The message includes `currentView` to show which template made the failing call.

Source

Thrown at lib/plugins/helper/partial.ts:20

import type Hexo from '../../hexo';
import type { LocalsType } from '../../types';

interface Options {
  cache?: boolean | string;
  only?: boolean;
}

export = (ctx: Hexo) => function partial(this: LocalsType, name: string, locals?: any, options: Options = {}) {
  if (typeof name !== 'string') throw new TypeError('name must be a string!');

  const { cache } = options;
  const viewDir = this.view_dir;
  const currentView = this.filename.substring(viewDir.length);
  const path = join(dirname(currentView), name);
  const view = ctx.theme.getView(path) || ctx.theme.getView(name);

  if (!view) {
    throw new Error(`Partial ${name} does not exist. (in ${currentView})`);
  }

  // Build locals lazily so a fragment cache hit does not copy the render context.
  const render = () => {
    const viewLocals: Record<string, any> = {};

    if (options.only) {
      Object.assign(viewLocals, locals);
    } else {
      Object.assign(viewLocals, this, locals);
    }

    // Partial don't need layout
    viewLocals.layout = false;

    return view.renderSync(viewLocals);
  };

View on GitHub (pinned to 059cb17494)

Solutions

  1. Confirm the partial file exists in the theme's `layout/` directory at the path Hexo resolves (account for the dirname-relative join: from `layout/post.ejs`, `partial('foo')` looks for `layout/post/foo`).
  2. Anchor the path explicitly: use `partial('_partial/share')` from a top-level layout, or `partial('../_partial/share')` when calling from a nested directory.
  3. Verify the file extension matches a renderer Hexo has loaded (.ejs / .njk / .pug) so `getView()` actually registers it.
  4. Check `_config.yml` `theme:` points to the installed theme that contains the partial.

Example fix

// before (called from layout/post.ejs -> resolves to layout/post/share)
<%- partial('share') %>

// after (anchored to the theme partial folder)
<%- partial('_partial/share') %>
// or, from a nested layout
<%- partial('../_partial/share') %>
Defensive patterns

Strategy: validation

Validate before calling

// Before rendering a layout that uses partial(), confirm the file is registered.
// Hexo resolves `partial(name)` relative to the calling view's directory first,
// then as a bare name. Check both candidate paths on disk:
const path = require('path');
const fs = require('fs');

function partialExists(themeDir, currentLayoutFile, name) {
  const rendererExt = ['.ejs', '.njk', '.pug', '.swig', '.hbs']; // adjust to loaded renderers
  const dir = path.dirname(currentLayoutFile);
  const candidates = [
    path.join(themeDir, 'layout', dir, name),
    path.join(themeDir, 'layout', name)
  ];
  return candidates.some(p =>
    rendererExt.some(ext => fs.existsSync(p + ext))
  );
}

// usage
if (!partialExists(hexo.theme_dir, 'post.ejs', '_partial/share')) {
  hexo.log.warn('Missing partial _partial/share');
}

Type guard

const isPartialName = (s: unknown): s is string =>
  typeof s === 'string' && s.trim().length > 0 && !s.includes(' ');

// usage before calling partial():
// if (!isPartialName(name)) throw new Error('invalid partial name');

Try / catch

// Wrap render in a script that treats a missing partial as non-fatal.
try {
  return hexo.theme.getView(name)?.renderSync(locals) ?? '';
} catch (e) {
  if (e instanceof Error && /Partial .* does not exist/.test(e.message)) {
    hexo.log.warn(`Skipping missing partial: ${e.message}`);
    return '';
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling `<%- partial('share') %>` (or `partial('_partial/foo')`) in a layout/partial when no file `share.*` / `_partial/foo.*` exists in the theme's `layout` directory at the resolved path. Because the path is joined with `dirname(currentView)`, a call from `layout/post.ejs` with name `foo` looks for `layout/post/foo`, not `layout/foo`.

Common situations: Typo in the partial name; forgetting the `_partial/` prefix; calling a partial from a nested layout without `../` anchoring; theme not installed or wrong `theme:` in `_config.yml`; renderer extension mismatch (theme is .njk but only a .ejs file exists); partial file added but not under `layout/`.

Related errors


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