angular/angular-cli · error · Error

Could not find the main bundle

Error message

Could not find the main bundle: ${serverBundlePath}

What it means

During prerendering, after the browser build completes, the prerender builder expects a corresponding server build's `main.js` bundle in the server output directory (per locale). This error is thrown in `_renderUniversal` when `main.js` cannot be found at the computed `serverBundlePath`, meaning the server bundle is missing or named differently. The library throws it because rendering routes requires loading the server bundle to execute Angular Universal.

Solutions

  1. Run the server builder first (ng run <project>:server) and verify `main.js` exists in the server output directory.
  2. Ensure `prerender` target's `browserTarget` and `serverTarget` point at configurations whose outputPath matches and whose output is not hashed/renamed.
  3. Check the server tsconfig/webpack config for custom output filenames and restore `main.js` as the bundle name.
  4. Delete the output folder and rebuild both browser and server targets to rule out stale/corrupt output.

Example fix

// angular.json - prerender target pointing only at browser build
"options": { "browserTarget": "app:build" }
// after: include the server target output and default filenames
"options": { "browserTarget": "app:build", "serverTarget": "app:server" }
Defensive patterns

Strategy: validation

Validate before calling

import * as fs from 'fs';
import * as path from 'path';
const serverBundlePath = path.join(serverOutputPath, localeDir ?? '', 'main.js');
if (!fs.existsSync(serverBundlePath)) {
  throw new Error(`Run the server target first; missing bundle: ${serverBundlePath}`);
}

Prevention

When it happens

Trigger: Running `ng run <project>:prerender` (or dev-server with prerendering/SRG) where `fs.existsSync(serverBundlePath)` fails because the server build output does not contain `main.js` at `<server-output>/<locale-dir>/main.js`.

Common situations: The project's server builder output was renamed or the server tsconfig outputs a bundle under a different filename; the server build target was not built or was configured with a different outputPath; custom webpack configuration changes the output filename; cleaning the output directory removed the server bundle; upgrading Angular changed the server bundle filename (e.g. `main.js` vs hashed names).

Related errors


AI-assisted analysis of angular/angular-cli@bb72145f9a (2026-08-30). Data as JSON: /api/errors/bc0f58641419ab43. Report an issue: GitHub.

Appendix: source

Thrown at packages/angular_devkit/build_angular/src/builders/prerender/index.ts:198

  const { baseOutputPath = '' } = serverResult;
  const worker = new Piscina({
    filename: path.join(__dirname, 'render-worker.js'),
    maxThreads: maxWorkers,
    workerData: { zonePackage },
    recordTiming: false,
  });

  let routes: string[] | undefined;

  try {
    // We need to render the routes for each locale from the browser output.
    for (const { path: outputPath } of browserResult.outputs) {
      const localeDirectory = path.relative(browserResult.baseOutputPath, outputPath);
      const serverBundlePath = path.join(baseOutputPath, localeDirectory, 'main.js');

      if (!fs.existsSync(serverBundlePath)) {
        throw new Error(`Could not find the main bundle: ${serverBundlePath}`);
      }

      routes ??= await getRoutes(
        indexFile,
        outputPath,
        serverBundlePath,
        options,
        context.workspaceRoot,
      );

      const spinner = ora(`Prerendering ${routes.length} route(s) to ${outputPath}...`).start();

      try {
        const results = (await Promise.all(
          routes.map((route) => {
            const options: RenderOptions = {
              indexFile,
              deployUrl: browserOptions.deployUrl || '',

View on GitHub (pinned to bb72145f9a)