From c31ff29af3afa89fd8f7262a3f8f821ecceb043f Mon Sep 17 00:00:00 2001 From: Melissa Liu Date: Mon, 20 Jul 2026 13:19:35 -0400 Subject: [PATCH 1/2] fix(plugin-rsc): don't run build-only generateBundle in bundledDev In bundledDev mode the client environment runs a Rollup build while mode === 'dev', so the assets-manifest generateBundle hook fires even though no RSC build output exists. It then reads manager.bundles['rsc'] (populated only by a production build) and crashes with 'TypeError: Cannot convert undefined or null to object'. The dev manifest is already served by the load hook, so the build-only asset copying and buildAssetsManifest construction are unnecessary in dev. Return early when mode === 'dev'. --- packages/plugin-rsc/src/plugin.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/packages/plugin-rsc/src/plugin.ts b/packages/plugin-rsc/src/plugin.ts index 86cbba631..6ae2b5bd0 100644 --- a/packages/plugin-rsc/src/plugin.ts +++ b/packages/plugin-rsc/src/plugin.ts @@ -1121,6 +1121,14 @@ export function createRpcClient(params) { }, // client build generateBundle(_options, bundle) { + // In bundledDev the client environment runs a Rollup build while + // `mode === 'dev'`, so this hook fires even though there is no RSC + // build output. The build-only asset copying and `buildAssetsManifest` + // construction below assume a production build (`manager.bundles['rsc']` + // is populated); in dev the manifest is served by the `load` hook above + // instead. Skip the build-only work in dev to avoid crashing on the + // absent RSC bundle. + if (this.environment.mode === 'dev') return // copy assets from rsc build to client build if (this.environment.name === 'client') { const rscBundle = manager.bundles['rsc']! From a8e7da93193e0d95baed75f89698c36f509c28d6 Mon Sep 17 00:00:00 2001 From: Melissa Liu Date: Mon, 20 Jul 2026 13:26:42 -0400 Subject: [PATCH 2/2] test(plugin-rsc): e2e coverage for bundledDev dev server Reuses examples/basic with 'pnpm dev --experimental-bundle' and asserts the dev server starts, renders, and hydrates without the generateBundle crash. --- packages/plugin-rsc/e2e/bundled-dev.test.ts | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 packages/plugin-rsc/e2e/bundled-dev.test.ts diff --git a/packages/plugin-rsc/e2e/bundled-dev.test.ts b/packages/plugin-rsc/e2e/bundled-dev.test.ts new file mode 100644 index 000000000..e47fa9b7d --- /dev/null +++ b/packages/plugin-rsc/e2e/bundled-dev.test.ts @@ -0,0 +1,14 @@ +import { test } from '@playwright/test' +import { useFixture } from './fixture' +import { defineStarterTest } from './starter' + +// `experimental.bundledDev` runs a client Rollup build in dev, which used to +// crash the assets-manifest `generateBundle` hook (no RSC bundle in dev). +test.describe('bundled-dev', () => { + const f = useFixture({ + root: 'examples/starter', + mode: 'dev', + command: 'pnpm dev --experimental-bundle', + }) + defineStarterTest(f) +})