angular/angular-cli · error

Invalid target string:

Error message

Invalid target string: 

What it means

targetFromTargetString parses a 'project[:target[:configuration]]' specifier. It throws when the string doesn't contain at least one colon, i.e. it cannot yield a project and target pair.

Source

Thrown at packages/angular_devkit/architect/src/api.ts:343

/**
 * Returns a string of "project:target[:configuration]" for the target object.
 */
export function targetStringFromTarget({ project, target, configuration }: Target) {
  return `${project}:${target}${configuration !== undefined ? ':' + configuration : ''}`;
}

/**
 * Return a Target tuple from a specifier string.
 * Supports abbreviated target specifiers (examples: `::`, `::development`, or `:build:production`).
 */
export function targetFromTargetString(
  specifier: string,
  abbreviatedProjectName?: string,
  abbreviatedTargetName?: string,
): Target {
  const tuple = specifier.split(':', 3);
  if (tuple.length < 2) {
    throw new Error('Invalid target string: ' + JSON.stringify(specifier));
  }

  return {
    project: tuple[0] || abbreviatedProjectName || '',
    target: tuple[1] || abbreviatedTargetName || '',
    ...(tuple[2] !== undefined && { configuration: tuple[2] }),
  };
}

/**
 * Schedule a target, and forget about its run. This will return an observable of outputs, that
 * as a teardown will stop the target from running. This means that the Run object this returns
 * should not be shared.
 *
 * The reason this is not part of the Context interface is to keep the Context as normal form as
 * possible. This is really an utility that people would implement in their project.
 *
 * @param context The context of your current execution.

View on GitHub (pinned to bb72145f9a)

Solutions

  1. Pass a full specifier like 'my-app:build' (or 'my-app:build:production')
  2. Trim/sanitize the input string before calling (strip stray colons/whitespace)
  3. For project-only input, resolve the default target yourself via the architect host before converting

Example fix

// before
const target = targetFromTargetString(process.env.TARGET);
// after
const spec = process.env.TARGET;
if (!spec || !spec.includes(':')) throw new Error('TARGET must be like project:target');
const target = targetFromTargetString(spec);
Defensive patterns

Strategy: validation

Validate before calling

function isValidTargetSpecifier(s) {
  return typeof s === 'string' && /^[^:]+:[^:]+(:[^:]+)?$/.test(s);
}
if (!isValidTargetSpecifier(spec)) throw new Error(`Not a target specifier: ${spec}`);

Type guard

function isTargetLike(v) {
  return typeof v === 'string' && v.split(':').filter(Boolean).length >= 2;
}

Try / catch

try {
  const target = targetFromTargetString(spec);
} catch (e) {
  if (e.message.startsWith('Invalid target string')) {
    console.error(`"${spec}" must look like project:target[:configuration]`);
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling targetFromTargetString('my-app') or targetFromTargetString('') — a string whose split(':') produces fewer than 2 segments.

Common situations: Passing a bare project name from CLI args or config instead of a project:target pair; typos like 'app-' or 'app::'; reading a target name from env vars that are unset or malformed.

Related errors


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