angular/angular-cli · error

The builder requires a target.

Error message

The builder requires a target.

What it means

The app-shell builder's _renderUniversal needs context.target.project to know which Angular project to render and to look up project metadata. Architect contexts normally carry a target; this error means the builder was invoked without one, so the target project cannot be resolved.

Source

Thrown at packages/angular_devkit/build_angular/src/builders/app-shell/index.ts:54

  const browserTarget = targetFromTargetString(options.browserTarget);
  const rawBrowserOptions = await context.getTargetOptions(browserTarget);
  const browserBuilderName = await context.getBuilderNameForTarget(browserTarget);
  const browserOptions = await context.validateOptions<JsonObject & BrowserBuilderSchema>(
    rawBrowserOptions,
    browserBuilderName,
  );

  // Locate zone.js to load in the render worker
  const root = context.workspaceRoot;
  let zonePackage: string | undefined;

  try {
    zonePackage = require.resolve('zone.js', { paths: [root] });
  } catch {}

  const projectName = context.target && context.target.project;
  if (!projectName) {
    throw new Error('The builder requires a target.');
  }

  const projectMetadata = await context.getProjectMetadata(projectName);
  const projectRoot = path.join(root, (projectMetadata.root as string | undefined) ?? '');

  const { styles } = normalizeOptimization(browserOptions.optimization);
  let inlineCriticalCssProcessor;
  if (styles.inlineCritical) {
    const { InlineCriticalCssProcessor } = await import('@angular/build/private');
    inlineCriticalCssProcessor = new InlineCriticalCssProcessor({
      minify: styles.minify,
      deployUrl: browserOptions.deployUrl,
    });
  }

  const renderWorker = new Piscina({
    filename: require.resolve('./render-worker'),
    maxThreads: 1,

View on GitHub (pinned to bb72145f9a)

Solutions

  1. Run the builder via ng run <project>:app-shell or architect.scheduleTarget() with a proper target spec.
  2. If constructing a context manually, set context.target = { project: 'your-app', builder: '...', target: 'app-shell' }.
  3. Ensure angular.json contains the project referenced by the target.

Example fix

// before (manual context)
await appShellBuilder(options, { root, workspaceRoot, logger } as any);
// after
const context = { root, workspaceRoot, logger, target: { project: 'my-app', target: 'app-shell', configuration: 'production' } } as any;
await appShellBuilder(options, context);
// or preferably: architect.scheduleTarget({ project: 'my-app', target: 'app-shell' })
Defensive patterns

Strategy: validation

Validate before calling

if (!context.target || !context.target.project) {
  throw new Error('app-shell must be scheduled via a target, e.g. ng run my-app:app-shell');
}

Type guard

function hasTargetProject(context: BuilderContext): context is BuilderContext & { target: { project: string } } {
  return typeof context.target?.project === 'string';
}

Try / catch

try {
  await architect.scheduleTarget({ project: 'my-app', target: 'app-shell' });
} catch (e) {
  if (e.message.includes('The builder requires a target')) {
    console.error('Invoke the builder with a valid target, not a bare function call');
  } else { throw e; }
}

Prevention

When it happens

Trigger: Executing the app-shell builder through an API path that passes no target (e.g. calling the builder function directly with a hand-built context lacking target), or scheduling it without a target specification.

Common situations: Custom tooling invoking builder functions programmatically with partially constructed ArchitectBuildContext; test harnesses that build contexts manually; integrations that call builders outside `ng run` / architect.scheduleTarget.

Related errors


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