anomalyco/sst · error · VisibleError
SSR server bundle not found in the build output at: "${pat
Error message
SSR server bundle not found in the build output at:
"${path.resolve(distPath)}".
Expected either Astro v5 output in `dist/_worker.js/index.js` or Astro v6+ output in `dist/server/wrangler.json`.
If your Astro project is entirely pre-rendered, use the `sst.cloudflare.StaticSite` component instead of `sst.cloudflare.Astro`. What it means
sst.cloudflare.Astro expects the Astro build to produce an SSR server bundle, but after running `astro build` no recognized server output was found at the configured dist path. SST supports Astro v5 layout (`dist/_worker.js/index.js`) and Astro v6+ layout (`dist/server/wrangler.json`). If the site is fully static (no SSR/on-demand routes), Astro produces no server bundle and the StaticSite component must be used instead.
Source
Thrown at platform/src/components/cloudflare/astro.ts:329
const wrangler = JSON.parse(
await fs.readFile(wranglerPath, "utf-8"),
) as WranglerConfig;
const main = wrangler.main ?? "entry.mjs";
const serverEntry = path.resolve(serverPath, main);
const assetsDirectory = wrangler.assets?.directory;
const assetsPath = assetsDirectory
? path.resolve(serverPath, assetsDirectory)
: path.join(distPath, "client");
if (await existsAsync(serverEntry)) {
return {
server: toRelativePath(serverEntry),
assets: toRelativePath(assetsPath),
};
}
}
throw new VisibleError(
`SSR server bundle not found in the build output at:\n` +
` "${path.resolve(distPath)}".\n\n` +
`Expected either Astro v5 output in \`dist/_worker.js/index.js\` or Astro v6+ output in \`dist/server/wrangler.json\`.\n` +
`If your Astro project is entirely pre-rendered, use the \`sst.cloudflare.StaticSite\` component instead of \`sst.cloudflare.Astro\`.`,
);
function toRelativePath(filePath: string) {
const relative = path.relative(outputPath, filePath);
return relative.startsWith(".") ? relative : `./${relative}`;
}
});
}
/**
* The URL of the Astro site.
*
* If the `domain` is set, this is the URL with the custom domain.
* Otherwise, it's the auto-generated Worker URL.View on GitHub (pinned to a0bd20f762)
Solutions
- If the site is entirely pre-rendered, replace `sst.cloudflare.Astro` with `sst.cloudflare.StaticSite` in your sst.config.ts.
- If you need SSR, set `output: 'server'` (or use on-demand rendering) in astro.config.mjs and rebuild.
- Run the Astro build and confirm the expected bundle exists (`dist/_worker.js/index.js` for v5, `dist/server/wrangler.json` for v6+).
- Ensure the component's `path`/build output settings point at the directory Astro actually writes to.
Example fix
// before (sst.config.ts)
const site = new sst.cloudflare.Astro(ctx, "Site", {});
// after (for a fully static site)
const site = new sst.cloudflare.StaticSite(ctx, "Site", {
path: "my-astro-app",
build: { output: "dist" },
}); Defensive patterns
Strategy: validation
Validate before calling
import fs from "fs";
import path from "path";
const dist = "my-astro-app/dist";
const isV5 = fs.existsSync(path.join(dist, "_worker.js/index.js"));
const isV6 = fs.existsSync(path.join(dist, "server/wrangler.json"));
if (!isV5 && !isV6) console.warn("No SSR bundle: use sst.cloudflare.StaticSite or set output: 'server'"); Type guard
const hasSsrOutput = (dist: string) => fs.existsSync(path.join(dist, "_worker.js/index.js")) || fs.existsSync(path.join(dist, "server/wrangler.json"));
Try / catch
try {
new sst.cloudflare.Astro(app, "Site", {});
} catch (e) {
if (String(e).includes("SSR server bundle not found")) {
// fall back to StaticSite or fix astro output config
} else throw e;
} Prevention
- Set `output: 'server'` in astro.config.mjs for SSR apps.
- Use sst.cloudflare.StaticSite for fully pre-rendered Astro sites.
- Run `astro build` before `sst deploy` and check the dist layout.
- Pin Astro version and confirm its output layout matches SST's expectations.
When it happens
Trigger: Running `sst deploy` (buildPlan in platform/src/components/cloudflare/astro.ts) after an Astro build where neither `dist/_worker.js/index.js` nor `dist/server/wrangler.json` exists — typically because `output: 'static'` is set in astro.config, or because the build never ran / ran into a different dist directory.
Common situations: Astro project configured as fully static but wrapped in sst.cloudflare.Astro; Astro build failed silently or was skipped; `dist` directory stale or cleaned; Astro version mismatch producing an unexpected output layout; custom `outDir` not matching what SST inspects.
Related errors
- SSR server bundle "index.mjs" not found in the build output
- React Router server bundle not found at: "${serverPath}".
- React Router assets directory not found at: "${assetsPath}
- TanStack Start build output not found in "${path.resolve(out
- TanStack Start build output at "${path.resolve(wranglerPath)
AI-assisted analysis of anomalyco/sst@a0bd20f762 (2026-08-30).
Data as JSON: /api/errors/801d9dff4c09e8c9.
Report an issue: GitHub.