angular/angular-cli · error · Error

Invalid config found at ${wksp.filePath}. `extensions.cli` s

Error message

Invalid config found at ${wksp.filePath}. `extensions.cli` should be an object.

What it means

Thrown by setCompletionConfig when the global workspace's `extensions.cli` value exists but is not a JSON object (e.g. a string, number, or array). The CLI expects `extensions.cli` to be an object so it can write `cli.completion`; a malformed value would otherwise be silently overwritten or corrupted.

Source

Thrown at packages/angular/cli/src/utilities/completion.ts:116

  return undefined;
}

async function getCompletionConfig(): Promise<CompletionConfig | undefined> {
  const wksp = await getWorkspace('global');

  return wksp?.getCli()?.['completion'];
}

async function setCompletionConfig(config: CompletionConfig): Promise<void> {
  const wksp = await getWorkspace('global');
  if (!wksp) {
    throw new Error(`Could not find global workspace`);
  }

  wksp.extensions['cli'] ??= {};
  const cli = wksp.extensions['cli'];
  if (!json.isJsonObject(cli)) {
    throw new Error(
      `Invalid config found at ${wksp.filePath}. \`extensions.cli\` should be an object.`,
    );
  }
  cli.completion = config as json.JsonObject;
  await wksp.save();
}

async function shouldPromptForAutocompletionSetup(
  command: string,
  config?: CompletionConfig,
): Promise<boolean> {
  // Force whether or not to prompt for autocomplete to give an easy path for e2e testing to skip.
  if (forceAutocomplete !== undefined) {
    return forceAutocomplete;
  }

  // Don't prompt on `ng update`, 'ng version' or `ng completion`.
  if (['version', 'update', 'completion'].includes(command)) {

View on GitHub (pinned to bb72145f9a)

Solutions

  1. Open the file reported in the error message (wksp.filePath, typically the global angular config) and change `extensions.cli` to an object, e.g. "cli": { "completion": {} }.
  2. Delete the malformed `cli` key (or the whole file) and let the CLI regenerate a valid config on the next run.
  3. Fix any tooling/sync process that wrote the scalar value to extensions.cli.
  4. Wrap the setup flow in try/catch to log and skip completion setup when the global config is malformed.

Example fix

// before (global angular config)
{ "extensions": { "cli": true } }
// after
{ "extensions": { "cli": { "completion": { "prompted": true } } } }
Defensive patterns

Strategy: validation

Validate before calling

import { json } from '@angular-devkit/core';
const config = JSON.parse(fs.readFileSync(globalConfigPath, 'utf8'));
const cli = config?.extensions?.cli;
if (cli !== undefined && !json.isJsonObject(cli)) {
  throw new Error(`${globalConfigPath}: extensions.cli must be an object, got ${typeof cli}`);
}

Type guard

function isJsonObject(v: unknown): v is Record<string, json.JsonValue> {
  return typeof v === 'object' && v !== null && !Array.isArray(v);
}

Try / catch

try {
  await setCompletionConfig(config);
} catch (err) {
  if ((err as Error).message.includes('`extensions.cli` should be an object')) {
    logger.error(`Fix extensions.cli in the file named in the error (set it to an object)`);
  } else throw err;
}

Prevention

When it happens

Trigger: The global Angular config file contains a `cli` entry under extensions whose value is a non-object (manually edited file, older/corrupted config, or another tool writing a scalar to that key), and any ng command triggers considerSettingUpAutocompletion -> setCompletionConfig.

Common situations: Users hand-editing their global Angular config and setting `"cli": true` or a string, config files damaged by editors or sync tools, or configs written by tooling incompatible with the CLI's schema.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


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