{"record":{"id":"26f90c73061198bf","repo":"hexojs/hexo","slug":"partial-name-does-not-exist-in-currentview","errorCode":null,"errorMessage":"Partial ${name} does not exist. (in ${currentView})","messagePattern":"Partial (.+?) does not exist\\. \\(in (.+?)\\)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"lib/plugins/helper/partial.ts","lineNumber":20,"sourceCode":"import type Hexo from '../../hexo';\nimport type { LocalsType } from '../../types';\n\ninterface Options {\n  cache?: boolean | string;\n  only?: boolean;\n}\n\nexport = (ctx: Hexo) => function partial(this: LocalsType, name: string, locals?: any, options: Options = {}) {\n  if (typeof name !== 'string') throw new TypeError('name must be a string!');\n\n  const { cache } = options;\n  const viewDir = this.view_dir;\n  const currentView = this.filename.substring(viewDir.length);\n  const path = join(dirname(currentView), name);\n  const view = ctx.theme.getView(path) || ctx.theme.getView(name);\n\n  if (!view) {\n    throw new Error(`Partial ${name} does not exist. (in ${currentView})`);\n  }\n\n  // Build locals lazily so a fragment cache hit does not copy the render context.\n  const render = () => {\n    const viewLocals: Record<string, any> = {};\n\n    if (options.only) {\n      Object.assign(viewLocals, locals);\n    } else {\n      Object.assign(viewLocals, this, locals);\n    }\n\n    // Partial don't need layout\n    viewLocals.layout = false;\n\n    return view.renderSync(viewLocals);\n  };\n","sourceCodeStart":2,"sourceCodeEnd":38,"githubUrl":"https://github.com/hexojs/hexo/blob/059cb17494d0632a053c24077f5bcb6ae92acc51/lib/plugins/helper/partial.ts#L2-L38","documentation":"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.","triggerScenarios":"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`.","commonSituations":"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/`.","solutions":["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`).","Anchor the path explicitly: use `partial('_partial/share')` from a top-level layout, or `partial('../_partial/share')` when calling from a nested directory.","Verify the file extension matches a renderer Hexo has loaded (.ejs / .njk / .pug) so `getView()` actually registers it.","Check `_config.yml` `theme:` points to the installed theme that contains the partial."],"exampleFix":"// before (called from layout/post.ejs -> resolves to layout/post/share)\n<%- partial('share') %>\n\n// after (anchored to the theme partial folder)\n<%- partial('_partial/share') %>\n// or, from a nested layout\n<%- partial('../_partial/share') %>","handlingStrategy":"validation","validationCode":"// Before rendering a layout that uses partial(), confirm the file is registered.\n// Hexo resolves `partial(name)` relative to the calling view's directory first,\n// then as a bare name. Check both candidate paths on disk:\nconst path = require('path');\nconst fs = require('fs');\n\nfunction partialExists(themeDir, currentLayoutFile, name) {\n  const rendererExt = ['.ejs', '.njk', '.pug', '.swig', '.hbs']; // adjust to loaded renderers\n  const dir = path.dirname(currentLayoutFile);\n  const candidates = [\n    path.join(themeDir, 'layout', dir, name),\n    path.join(themeDir, 'layout', name)\n  ];\n  return candidates.some(p =>\n    rendererExt.some(ext => fs.existsSync(p + ext))\n  );\n}\n\n// usage\nif (!partialExists(hexo.theme_dir, 'post.ejs', '_partial/share')) {\n  hexo.log.warn('Missing partial _partial/share');\n}","typeGuard":"const isPartialName = (s: unknown): s is string =>\n  typeof s === 'string' && s.trim().length > 0 && !s.includes(' ');\n\n// usage before calling partial():\n// if (!isPartialName(name)) throw new Error('invalid partial name');","tryCatchPattern":"// Wrap render in a script that treats a missing partial as non-fatal.\ntry {\n  return hexo.theme.getView(name)?.renderSync(locals) ?? '';\n} catch (e) {\n  if (e instanceof Error && /Partial .* does not exist/.test(e.message)) {\n    hexo.log.warn(`Skipping missing partial: ${e.message}`);\n    return '';\n  }\n  throw e;\n}","preventionTips":["Keep all partials under layout/_partial/ and always reference them as `_partial/<name>` to avoid dirname-relative surprises.","Add a CI check that greps templates for `partial(...)` calls and asserts each resolves to a file under `layout/`.","After switching themes, run `hexo clean && hexo generate` so the view registry is rebuilt.","Use consistent template extensions across the theme so getView() registers every file."],"tags":["hexo","theme","partial","template","rendering"],"backgroundTag":null,"analyzedSha":"059cb17494d0632a053c24077f5bcb6ae92acc51","analyzedAt":"2026-08-12T20:52:05.731Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}