angular/angular-cli · error · Error

The builder requires a target.

Error message

The builder requires a target.

What it means

configureI18nBuild needs the builder's target (from the Architect scheduler) to read project metadata such as source root and i18n options. When context.target is null — e.g. when the builder is invoked programmatically or via an API without a target — it cannot resolve project configuration and throws.

Source

Thrown at packages/angular_devkit/build_angular/src/utils/i18n-webpack.ts:40

import { readTsconfig } from '../utils/read-tsconfig';

/**
 * The base module location used to search for locale specific data.
 */
const LOCALE_DATA_BASE_MODULE = '@angular/common/locales/global';

// Re-export for use within Webpack related builders
export { I18nOptions, loadTranslations };

export async function configureI18nBuild<T extends BrowserBuilderSchema | ServerBuilderSchema>(
  context: BuilderContext,
  options: T,
): Promise<{
  buildOptions: T;
  i18n: I18nOptions;
}> {
  if (!context.target) {
    throw new Error('The builder requires a target.');
  }

  const buildOptions = { ...options };
  const tsConfig = await readTsconfig(buildOptions.tsConfig, context.workspaceRoot);
  const metadata = await context.getProjectMetadata(context.target);
  const i18n = createI18nOptions(metadata, buildOptions.localize, context.logger);

  // No additional processing needed if no inlining requested and no source locale defined.
  if (!i18n.shouldInline && !i18n.hasDefinedSourceLocale) {
    return { buildOptions, i18n };
  }

  const projectRoot = path.join(context.workspaceRoot, (metadata.root as string) || '');
  // The trailing slash is required to signal that the path is a directory and not a file.
  const projectRequire = createRequire(projectRoot + '/');
  const localeResolver = (locale: string) =>
    projectRequire.resolve(path.join(LOCALE_DATA_BASE_MODULE, locale));

View on GitHub (pinned to bb72145f9a)

Solutions

  1. Invoke the build via `ng build` so a target (project:builder) is always provided.
  2. When scheduling programmatically, pass the target: `context.scheduler.schedule(':@project:builder:configuration', options)` with a named project/builder.
  3. In tests, construct a fake BuilderContext whose `target` is set to a valid Target object.
  4. Refactor to call createI18nOptions directly with project metadata if you don't need target-based resolution.

Example fix

// before (programmatic)
await context.scheduler.schedule('ng:build', options);
// after
await context.scheduler.schedule('@angular-devkit/build-angular:browser:production', options);
Defensive patterns

Strategy: try-catch

Validate before calling

if (!context.target) throw new Error('configureI18nBuild requires context.target; schedule the builder via a named target.');

Type guard

function hasTarget(ctx: BuilderContext): ctx is BuilderContext & { target: Target } {
  return !!ctx.target && typeof ctx.target.project === 'string';
}

Try / catch

try {
  await configureI18nBuild(context, options);
} catch (err) {
  if (err.message === 'The builder requires a target.') {
    console.error('Run via `ng build` or schedule with a fully qualified target (project:builder:configuration).');
  } else throw err;
}

Prevention

When it happens

Trigger: Invoking a builder through architect schedule with no explicit target, calling the builder API directly (e.g. in tests or a custom tool) without providing target in the BuilderContext, or running from tooling that strips target information.

Common situations: Custom scripts calling builder handlers directly; unit tests instantiating the builder context without a target; third-party tooling wrapping the CLI builders programmatically.

Related errors


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