vuejs/vue · error · Error
bundle export should be a function when using { runInNewCont
Error message
bundle export should be a function when using { runInNewContext: false }. What it means
Thrown by createBundleRunner when runInNewContext is false (or 'once') and the bundle's entry export, after evaluation, is not a function. In direct mode (runInNewContext: false) the runner is evaluated once and then invoked as runner(userContext) on every render — so the export must be a callable function. In new-context mode the export is allowed to be a component object because the whole bundle re-evaluates each render.
Source
Thrown at packages/server-renderer/src/bundle-renderer/create-bundle-runner.ts:127
// module evaluation costs but requires the source code to be structured
// slightly differently.
let runner // lazy creation so that errors can be caught by user
let initialContext
return (userContext = {}) =>
new Promise(resolve => {
if (!runner) {
const sandbox = runInNewContext === 'once' ? createSandbox() : global
// the initial context is only used for collecting possible non-component
// styles injected by vue-style-loader.
// @ts-expect-error
initialContext = sandbox.__VUE_SSR_CONTEXT__ = {}
runner = evaluate(entry, sandbox)
// On subsequent renders, __VUE_SSR_CONTEXT__ will not be available
// to prevent cross-request pollution.
// @ts-expect-error
delete sandbox.__VUE_SSR_CONTEXT__
if (typeof runner !== 'function') {
throw new Error(
'bundle export should be a function when using ' +
'{ runInNewContext: false }.'
)
}
}
// @ts-expect-error
userContext._registeredComponents = new Set()
// vue-style-loader styles imported outside of component lifecycle hooks
if (initialContext._styles) {
// @ts-expect-error
userContext._styles = deepClone(initialContext._styles)
// #6353 ensure "styles" is exposed even if no styles are injected
// in component lifecycles.
// the renderStyles fn is exposed by vue-style-loader >= 3.0.3
const renderStyles = initialContext._renderStyles
if (renderStyles) {
Object.defineProperty(userContext, 'styles', {View on GitHub (pinned to 9e88707940)
Solutions
- Set webpack output.libraryTarget to 'commonjs2' so the entry exports a callable function.
- Ensure the SSR entry exports a function: `export default context => { /* create app, return app or promise */ }`.
- If the bundle cannot be restructured, use runInNewContext: true (default) which accepts an object export.
- Verify the built bundle's last line: with commonjs2 it should be module.exports = function (...) {...}.
Example fix
// before — entry exports an object, fails with runInNewContext: false
export default new Vue({ ... })
// after — entry exports a function
export default context => {
return new Promise((resolve, reject) => {
const app = new Vue({ ... })
resolve(app)
})
} Defensive patterns
Strategy: validation
Validate before calling
function assertBundleExportsFunction(entryPath: string): boolean {
// inspect the built bundle: with commonjs2, the last export should be a function
const src = fs.readFileSync(entryPath, 'utf-8')
// crude heuristic: module.exports = function or exports.default = function
return /module\.exports\s*=\s*function/.test(src) || /exports\.default\s*=\s*function/.test(src)
}
if (runInNewContext === false && !assertBundleExportsFunction(entryPath)) {
throw new Error('SSR entry must export a function when runInNewContext is false')
} Type guard
// Runtime check after evaluation
function isFunctionRunner(runner: unknown): runner is (ctx: any) => any {
return typeof runner === 'function'
} Try / catch
// The error is thrown inside the promise chain of run(context).
// Catch at the render call:
renderer.renderToString(context, (err, html) => {
if (err && err.message.includes('bundle export should be a function')) {
console.error('Fix webpack output.libraryTarget=commonjs2 and export a function from entry-server.js')
}
}) Prevention
- Set webpack output.libraryTarget to 'commonjs2' for the server build.
- Write the SSR entry as `export default context => { ... return app }` (a function).
- Add a post-build smoke test: require the bundle and assert typeof result === 'function'.
- Document the runInNewContext:false contract in your SSR setup docs.
When it happens
Trigger: Building an SSR bundle with output.libraryTarget set to var/jsonp or omitting commonjs2, so the entry module exports an object (the app factory) instead of a function. Also triggered by a bundle that does `export default { ... }` rather than `export default () => { ... }`.
Common situations: Webpack server config output.libraryTarget is not commonjs2. The entry file's default export is the app instance or options object rather than a function that creates the app. Switching from runInNewContext: true to false without restructuring the entry.
Related errors
- Entry "${entryName}" not found. Did you specify the correct
- Server-side bundle should have one single entry file. Avoid
- \n\nVue packages version mismatch:\n\n- vue@${vueVersion}\n-
- Invalid JSON bundle file: ${bundle}
- Cannot locate bundle file: ${bundle}
AI-assisted analysis of vuejs/vue@9e88707940 (2026-08-11).
Data as JSON: /api/errors/0b32ef1cdf891bef.
Report an issue: GitHub.