{"record":{"id":"0b32ef1cdf891bef","repo":"vuejs/vue","slug":"bundle-export-should-be-a-function-when-using-ru","errorCode":null,"errorMessage":"bundle export should be a function when using { runInNewContext: false }.","messagePattern":"bundle export should be a function when using (.+?)\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/server-renderer/src/bundle-renderer/create-bundle-runner.ts","lineNumber":127,"sourceCode":"    // module evaluation costs but requires the source code to be structured\n    // slightly differently.\n    let runner // lazy creation so that errors can be caught by user\n    let initialContext\n    return (userContext = {}) =>\n      new Promise(resolve => {\n        if (!runner) {\n          const sandbox = runInNewContext === 'once' ? createSandbox() : global\n          // the initial context is only used for collecting possible non-component\n          // styles injected by vue-style-loader.\n          // @ts-expect-error\n          initialContext = sandbox.__VUE_SSR_CONTEXT__ = {}\n          runner = evaluate(entry, sandbox)\n          // On subsequent renders, __VUE_SSR_CONTEXT__ will not be available\n          // to prevent cross-request pollution.\n          // @ts-expect-error\n          delete sandbox.__VUE_SSR_CONTEXT__\n          if (typeof runner !== 'function') {\n            throw new Error(\n              'bundle export should be a function when using ' +\n                '{ runInNewContext: false }.'\n            )\n          }\n        }\n        // @ts-expect-error\n        userContext._registeredComponents = new Set()\n\n        // vue-style-loader styles imported outside of component lifecycle hooks\n        if (initialContext._styles) {\n          // @ts-expect-error\n          userContext._styles = deepClone(initialContext._styles)\n          // #6353 ensure \"styles\" is exposed even if no styles are injected\n          // in component lifecycles.\n          // the renderStyles fn is exposed by vue-style-loader >= 3.0.3\n          const renderStyles = initialContext._renderStyles\n          if (renderStyles) {\n            Object.defineProperty(userContext, 'styles', {","sourceCodeStart":109,"sourceCodeEnd":145,"githubUrl":"https://github.com/vuejs/vue/blob/9e88707940088cb1f4cd7dd210c9168a50dc347c/packages/server-renderer/src/bundle-renderer/create-bundle-runner.ts#L109-L145","documentation":"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.","triggerScenarios":"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 () => { ... }`.","commonSituations":"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.","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 (...) {...}."],"exampleFix":"// before — entry exports an object, fails with runInNewContext: false\nexport default new Vue({ ... })\n\n// after — entry exports a function\nexport default context => {\n  return new Promise((resolve, reject) => {\n    const app = new Vue({ ... })\n    resolve(app)\n  })\n}","handlingStrategy":"validation","validationCode":"function assertBundleExportsFunction(entryPath: string): boolean {\n  // inspect the built bundle: with commonjs2, the last export should be a function\n  const src = fs.readFileSync(entryPath, 'utf-8')\n  // crude heuristic: module.exports = function or exports.default = function\n  return /module\\.exports\\s*=\\s*function/.test(src) || /exports\\.default\\s*=\\s*function/.test(src)\n}\n\nif (runInNewContext === false && !assertBundleExportsFunction(entryPath)) {\n  throw new Error('SSR entry must export a function when runInNewContext is false')\n}","typeGuard":"// Runtime check after evaluation\nfunction isFunctionRunner(runner: unknown): runner is (ctx: any) => any {\n  return typeof runner === 'function'\n}","tryCatchPattern":"// The error is thrown inside the promise chain of run(context).\n// Catch at the render call:\nrenderer.renderToString(context, (err, html) => {\n  if (err && err.message.includes('bundle export should be a function')) {\n    console.error('Fix webpack output.libraryTarget=commonjs2 and export a function from entry-server.js')\n  }\n})","preventionTips":["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."],"tags":["ssr","bundle-runner","run-in-new-context","webpack","entry"],"analyzedSha":"9e88707940088cb1f4cd7dd210c9168a50dc347c","analyzedAt":"2026-08-11T22:22:01.295Z","schemaVersion":2},"datasetVersion":"2026-08-12T04:17:13.124Z"}