vuejs/core · error · Error
ESM build of renderToStream() does not support renderToNodeS
Error message
ESM build of renderToStream() does not support renderToNodeStream(). Use pipeToNodeWritable() with an existing Node.js Writable stream instance instead.
What it means
Thrown by renderToNodeStream in @vue/server-renderer's ESM build. renderToNodeStream constructs a Node `stream.Readable` via require('node:stream'), which only works in the CJS build; in the ESM build the require returns null and the guard at renderToStream.ts:116 throws. The message points to pipeToNodeWritable() as the ESM-compatible alternative.
Source
Thrown at packages/server-renderer/src/renderToStream.ts:116
input: App | VNode,
context: SSRContext = {},
): Readable {
console.warn(
`[@vue/server-renderer] renderToStream is deprecated - use renderToNodeStream instead.`,
)
return renderToNodeStream(input, context)
}
export function renderToNodeStream(
input: App | VNode,
context: SSRContext = {},
): Readable {
const stream: Readable = __CJS__
? new (require('node:stream').Readable)({ read() {} })
: null
if (!stream) {
throw new Error(
`ESM build of renderToStream() does not support renderToNodeStream(). ` +
`Use pipeToNodeWritable() with an existing Node.js Writable stream ` +
`instance instead.`,
)
}
return renderToSimpleStream(input, context, stream)
}
export function pipeToNodeWritable(
input: App | VNode,
context: SSRContext | undefined = {},
writable: Writable,
): void {
renderToSimpleStream(input, context, {
push(content) {
if (content != null) {
writable.write(content)View on GitHub (pinned to a2b40db9a8)
Solutions
- Use pipeToNodeWritable(input, context, existingWritable) instead — it accepts an already-created Node Writable stream and works in the ESM build.
- If you must keep renderToNodeStream, import the CJS build of @vue/server-renderer explicitly.
- Switch the server code to create the Writable (e.g. the HTTP response) and pipe into it via pipeToNodeWritable.
Example fix
// before (ESM build)
const stream = renderToNodeStream(app)
stream.pipe(res)
// after
pipeToNodeWritable(app, {}, res) Defensive patterns
Strategy: validation
Validate before calling
// Detect the ESM build and route to the writable API.
import { pipeToNodeWritable, renderToNodeStream } from '@vue/server-renderer'
async function ssrToResponse(app, res) {
// Prefer the universal pipe API; fall back only on the CJS build.
if (typeof pipeToNodeWritable === 'function') {
pipeToNodeWritable(app, {}, res)
} else {
renderToNodeStream(app).pipe(res)
}
} Type guard
function supportsRenderToNodeStream(): boolean {
// True only on the CJS build of @vue/server-renderer.
return typeof __CJS__ !== 'undefined' ? !!__CJS__ : false
} Prevention
- Use pipeToNodeWritable(app, ctx, res) as the default; it works across builds.
- Confirm which entry (esm vs cjs) your server resolves for @vue/server-renderer.
- Avoid copying renderToNodeStream from CJS examples into ESM projects.
When it happens
Trigger: Calling renderToNodeStream(input) from the ESM entry of @vue/server-renderer. This happens in pure-ESM Node projects or bundlers that pick the ESM build.
Common situations: Migrating an SSR server to native ESM (`"type": "module"`); a bundler resolving @vue/server-renderer to its ESM entry; copying renderToNodeStream usage from a CJS tutorial into an ESM project.
Related errors
- On-the-fly template compilation is not supported in the ESM
- ReadableStream constructor is not available in the global sc
- [@vue/compiler-core] decodeEntities option is required in br
- [@vue/compiler-sfc] <script> and <script setup> must have th
- [@vue/compiler-sfc] SFC contains no <script> tags.
AI-assisted analysis of vuejs/core@a2b40db9a8 (2026-08-12).
Data as JSON: /api/errors/732dcb37551c4a60.
Report an issue: GitHub.