angular/angular-cli · error · CommandError

No terminal detected

Error message

No terminal detected

What it means

confirmInstallationTask requires an interactive terminal to show the 'Would you like to proceed?' confirmation prompt. If `isTTY()` returns false, the CLI cannot prompt, prints a hint about `--skip-confirmation`, and throws this CommandError instead of hanging or auto-confirming.

Source

Thrown at packages/angular/cli/src/commands/add/cli.ts:578

    context.homepage = manifest.homepage;

    if (await this.getPeerDependencyConflicts(manifest)) {
      task.output = color.yellow(
        figures.warning +
          ' Package has unmet peer dependencies. Adding the package may not succeed.',
      );
    }
  }

  private async confirmInstallationTask(
    context: AddCommandTaskContext,
    task: AddCommandTaskWrapper,
  ): Promise<void> {
    if (!isTTY()) {
      task.output =
        `'--skip-confirmation' can be used to bypass installation confirmation. ` +
        `Ensure package name is correct prior to '--skip-confirmation' option usage.`;
      throw new CommandError('No terminal detected');
    }

    const { ListrInquirerPromptAdapter } = await import('@listr2/prompt-adapter-inquirer');
    const { confirm } = await import('@inquirer/prompts');
    const shouldProceed = await task.prompt(ListrInquirerPromptAdapter).run(confirm, {
      message:
        `The package ${color.blue(context.packageIdentifier.toString())} will be installed and executed.\n` +
        'Would you like to proceed?',
      default: true,
      theme: { prefix: '' },
    });

    if (!shouldProceed) {
      throw new CommandError('Command aborted');
    }
  }

  private async cleanUpTemporaryDependency(packageName: string): Promise<void> {

View on GitHub (pinned to bb72145f9a)

Solutions

  1. Add `--skip-confirmation` to the `ng add` command when no interactive terminal is available.
  2. Only run `ng add` interactively in a real terminal (not inside scripts/CI) without the flag.
  3. In CI, pre-install the package and invoke the schematic directly (e.g. `ng generate <package>:ng-add`) to avoid the prompt path.
  4. Ensure your terminal emulator allocates a pseudo-TTY if running in a container (`docker run -it`).

Example fix

// before
ng add @angular/material
// after
ng add @angular/material --skip-confirmation
Defensive patterns

Strategy: validation

Validate before calling

if (!process.stdin.isTTY || !process.stdout.isTTY) {
  args.push('--skip-confirmation'); // must be set before invoking ng add non-interactively
}

Type guard

function isInteractive(env: NodeJS.ProcessEnv = process.env, stdin: { isTTY?: boolean } = process.stdin): boolean {
  return stdin.isTTY === true && !env.CI;
}

Try / catch

try {
  const args = isInteractive() ? ['add', pkg] : ['add', pkg, '--skip-confirmation'];
  await exec('ng', args);
} catch (e) {
  if (e instanceof Error && e.message === 'No terminal detected') {
    console.error('ng add requires a TTY; rerun with --skip-confirmation.');
  }
  throw e;
}

Prevention

When it happens

Trigger: Running `ng add <package>` without `--skip-confirmation` in a non-interactive context: CI pipelines, docker builds, scripts/pipes where stdin/stdout is not a TTY.

Common situations: CI jobs (GitHub Actions, Jenkins, GitLab CI) running `ng add` in a script; Docker RUN commands; piping output (`ng add x | tee log`); IDE-embedded terminals without TTY emulation.

Related errors


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