vuejs/vue · error · Error

function template is only supported in renderToString.

Error message

function template is only supported in renderToString.

What it means

Thrown synchronously from renderer.renderToStream when the template option is a function. Function templates require the full rendered content up front (they receive content + context and return a string or promise), but renderToStream pipes output incrementally through a TemplateStream — there is no single moment where the complete content is available to hand to a function. Only renderToString supports function templates because it accumulates the full string first.

Source

Thrown at packages/server-renderer/src/create-renderer.ts:143

      if (context) {
        templateRenderer.bindRenderFns(context)
      }
      const renderStream = new RenderStream((write, done) => {
        // @ts-expect-error
        render(component, write, context, done)
      })
      if (!template) {
        // @ts-expect-error
        if (context && context.rendered) {
          // @ts-expect-error
          const rendered = context.rendered
          renderStream.once('beforeEnd', () => {
            rendered(context)
          })
        }
        return renderStream
      } else if (typeof template === 'function') {
        throw new Error(
          `function template is only supported in renderToString.`
        )
      } else {
        const templateStream = templateRenderer.createStream(context)
        renderStream.on('error', err => {
          templateStream.emit('error', err)
        })
        renderStream.pipe(templateStream)
        //@ts-expect-error
        if (context && context.rendered) {
          //@ts-expect-error
          const rendered = context.rendered
          renderStream.once('beforeEnd', () => {
            rendered(context)
          })
        }
        return templateStream
      }

View on GitHub (pinned to 9e88707940)

Solutions

  1. Use renderToString instead of renderToStream when a function template is required.
  2. If streaming is mandatory, switch the template to a string (HTML with <!--vue-ssr-outlet--> placeholder) so createStream can build a TemplateStream.
  3. Create two renderers: one with a string template for streaming, one without a template and do post-processing on the stream manually.

Example fix

// before
const renderer = createRenderer({
  template: (content, ctx) => `<html>...${content}...</html>`
})
renderer.renderToStream(app) // throws

// after — use renderToString for function templates
renderer.renderToString(app, (err, html) => { /* ... */ })
Defensive patterns

Strategy: validation

Validate before calling

function assertTemplateCompatibleWithStream(template: unknown): void {
  if (typeof template === 'function') {
    throw new Error(
      'Function templates are not supported by renderToStream. Use renderToString, or pass a string template.'
    )
  }
}

assertTemplateCompatibleWithStream(rendererOptions.template)
renderer.renderToStream(app)

Type guard

function isStreamCompatibleTemplate(template: unknown): boolean {
  return template === undefined || typeof template === 'string'
}

Try / catch

try {
  renderer.renderToStream(app, context)
} catch (e) {
  if (e.message.includes('function template is only supported in renderToString')) {
    // fall back to renderToString
    renderer.renderToString(app, context, cb)
  } else {
    throw e
  }
}

Prevention

When it happens

Trigger: Calling renderer.renderToStream(app, context) on a renderer created with { template: (content, ctx) => html } where template is a function rather than a string.

Common situations: Developer reuses a renderer configured for renderToString (with a function template) and calls renderToStream on the same instance. Migrating from string template to programmatic template without realizing stream rendering doesn't support it.

Related errors


AI-assisted analysis of vuejs/vue@9e88707940 (2026-08-11). Data as JSON: /api/errors/17f68b78ab708937. Report an issue: GitHub.