vuejs/vue · error · Error
render cannot be called without a template.
Error message
render cannot be called without a template.
What it means
Thrown by TemplateRenderer.render when called but parsedTemplate is null — meaning the renderer was created without a template option (template was undefined/false). render() is meant to wrap rendered app content with the surrounding HTML shell; without a parsed template there is nothing to wrap with. This is usually an internal path: createRenderer calls templateRenderer.render only when template is set, so hitting this means an explicit direct call or a logic regression.
Source
Thrown at packages/server-renderer/src/template-renderer/index.ts:113
const renderer: any = this
;['ResourceHints', 'State', 'Scripts', 'Styles'].forEach(type => {
context[`render${type}`] = renderer[`render${type}`].bind(
renderer,
context
)
})
// also expose getPreloadFiles, useful for HTTP/2 push
context.getPreloadFiles = renderer.getPreloadFiles.bind(renderer, context)
}
// render synchronously given rendered app content and render context
render(
content: string,
context: Record<string, any> | null
): string | Promise<string> {
const template = this.parsedTemplate
if (!template) {
throw new Error('render cannot be called without a template.')
}
context = context || {}
if (typeof template === 'function') {
return template(content, context)
}
if (this.inject) {
return (
template.head(context) +
(context.head || '') +
this.renderResourceHints(context) +
this.renderStyles(context) +
template.neck(context) +
content +
this.renderState(context) +
this.renderScripts(context) +
template.tail(context)View on GitHub (pinned to 9e88707940)
Solutions
- Provide a template option when creating the renderer: createRenderer({ template: '<html>...<!--vue-ssr-outlet-->...</html>' }).
- If you called render() directly, guard it: if (!renderer.parsedTemplate) return content.
- Use a separate renderer instance for full-page rendering vs. asset rendering.
Example fix
// before
const renderer = createRenderer({}) // no template
const html = renderer.templateRenderer.render(content, ctx) // throws
// after
const renderer = createRenderer({
template: '<!DOCTYPE html><html><head></head><body><!--vue-ssr-outlet--></body></html>'
}) Defensive patterns
Strategy: validation
Validate before calling
function assertTemplateSet(templateRenderer: any): void {
if (!templateRenderer.parsedTemplate) {
throw new Error(
'TemplateRenderer.render called without a template. Pass a template to createRenderer.'
)
}
}
// if calling render directly:
assertTemplateSet(renderer.templateRenderer)
renderer.templateRenderer.render(content, ctx) Type guard
function hasParsedTemplate(tr: any): boolean {
return tr.parsedTemplate != null
} Try / catch
// Internal API — prefer not to call render() directly.
// Instead, ensure createRenderer was built with a template:
if (!options.template) {
throw new Error('Cannot use full-page rendering without a template option')
}
const renderer = createRenderer(options) Prevention
- Treat TemplateRenderer as internal; use the public createRenderer/renderToString API.
- Always pass a template option when full-page SSR is needed.
- Keep a single renderer instance per template configuration.
When it happens
Trigger: Manually calling templateRenderer.render(content, ctx) on a renderer built without a template. Or a code path in createRenderer.renderToString that reaches templateRenderer.render despite template being falsy due to a bug or monkeypatched options.
Common situations: A custom integration reaches into the internal templateRenderer instance. A renderer was created for asset/preload rendering only (no template) but later used for full-page rendering. Refactor that swapped renderer instances.
Related errors
- createStream cannot be called without a template.
- render function or template not defined in component: ${vm.$
- function template is only supported in renderToString.
- \n[31m${err}${trace}[39m\n
- Content placeholder not found in template.
AI-assisted analysis of vuejs/vue@9e88707940 (2026-08-11).
Data as JSON: /api/errors/8eed72ec2b5b99b0.
Report an issue: GitHub.