anomalyco/sst · error · VisibleError

React Router server bundle not found at: "${serverPath}".

Error message

React Router server bundle not found at:
  "${serverPath}".

Make sure the Cloudflare Vite plugin is configured in your `vite.config.ts`.
If your React Router project is entirely pre-rendered, use `sst.cloudflare.StaticSite` instead.

What it means

After building a React Router (Vite) app, SST expects the server bundle at `build/server/index.js` inside the output directory. If it's missing, SST can't create the Worker and throws with guidance: the Cloudflare Vite plugin likely isn't configured, or the app is fully pre-rendered and should be a StaticSite.

Source

Thrown at platform/src/components/cloudflare/react-router.ts:280

    super(__pulumiType, name, args, opts);
  }

  protected validate(sitePath: string): void {
    validateFrameworkConfig({
      sitePath,
      configName: "vite.config",
      componentName: "ReactRouter",
    });
    validateNoWranglerFile(sitePath, "ReactRouter");
  }

  protected buildPlan(outputPath: Output<string>): Output<Plan> {
    return outputPath.apply(async (outputPath) => {
      const serverPath = path.join(outputPath, "build", "server", "index.js");
      const assetsPath = path.join(outputPath, "build", "client");

      if (!(await existsAsync(serverPath))) {
        throw new VisibleError(
          [
            `React Router server bundle not found at:\n  "${serverPath}".`,
            "",
            "Make sure the Cloudflare Vite plugin is configured in your `vite.config.ts`.",
            "If your React Router project is entirely pre-rendered, use `sst.cloudflare.StaticSite` instead.",
          ].join("\n"),
        );
      }

      if (!(await existsAsync(assetsPath))) {
        throw new VisibleError(
          `React Router assets directory not found at:\n  "${assetsPath}".`,
        );
      }

      return {
        server: "./build/server/index.js",
        assets: "./build/client",

View on GitHub (pinned to a0bd20f762)

Solutions

  1. Add `@cloudflare/vite-plugin` to the plugins array in `vite.config.ts` and rebuild
  2. Verify the component's `path` points to the app directory containing `build/` (or the correct output dir)
  3. If the site is entirely pre-rendered, switch to `sst.cloudflare.StaticSite`
  4. Run the project's official build command (not a custom one that skips the server bundle) and confirm `build/server/index.js` exists

Example fix

// before (vite.config.ts)
plugins: [reactRouter()]
// after
import { cloudflare } from '@cloudflare/vite-plugin';
plugins: [reactRouter(), cloudflare()]
Defensive patterns

Strategy: validation

Validate before calling

import { existsSync } from 'fs';
import path from 'path';
const out = 'apps/web';
if (!existsSync(path.join(out, 'build', 'server', 'index.js')))
  throw new Error('React Router server bundle missing: run vite build with @cloudflare/vite-plugin');
new sst.cloudflare.ReactRouter('Site', { path: out });

Try / catch

// thrown during deploy/synth, catch around stack definition is atypical; detect pre-deploy
try {
  await deploy();
} catch (e) {
  if (/React Router server bundle not found/.test(e.message)) console.error('Enable the Cloudflare Vite plugin');
}

Prevention

When it happens

Trigger: Running `sst deploy` on a React Router project whose build lacks `build/server/index.js`: missing/incorrect `@cloudflare/vite-plugin` in vite.config.ts, wrong `path` in the component args, or a prerender-only build.

Common situations: Migrating a React Router SPA from Remix without adding the Cloudflare Vite plugin; running `vite build` instead of the project's ssg/build command; pointing the component at the project root instead of the build output directory.

Related errors


AI-assisted analysis of anomalyco/sst@a0bd20f762 (2026-08-30). Data as JSON: /api/errors/0a54205b9bf9efd7. Report an issue: GitHub.