angular/angular-cli · warning

Skipping invalid project value; expected an object.

Error message

Skipping invalid project value; expected an object.

What it means

While parsing the 'projects' section of angular.json, the reader skips any entry whose value is not a JSON object (or whose AST node is missing) and emits this warning instead of failing the whole workspace load.

Source

Thrown at packages/angular_devkit/core/src/workspace/json/reader.ts:160

      createVirtualAstObject(workspaceNodeValue, {
        exclude: ['$schema', 'version', 'projects'],
        listener(path, value) {
          jsonMetadata.addChange(path, value);
        },
      }),
  } as WorkspaceDefinition;
}

function parseProjectsObject(
  projectsNode: Node,
  context: ParserContext,
): Record<string, ProjectDefinition> {
  const projects: Record<string, ProjectDefinition> = Object.create(null);

  for (const [name, value] of Object.entries<JsonValue>(getNodeValue(projectsNode))) {
    const nodes = findNodeAtLocation(projectsNode, [name]);
    if (!isJsonObject(value) || !nodes) {
      context.warn('Skipping invalid project value; expected an object.', value);
      continue;
    }

    projects[name] = parseProject(name, nodes, context);
  }

  return projects;
}

function parseProject(
  projectName: string,
  projectNode: Node,
  context: ParserContext,
): ProjectDefinition {
  const jsonMetadata = context.metadata;
  let targets;
  let hasTargets = false;
  let extensions: Record<string, JsonValue> | undefined;

View on GitHub (pinned to bb72145f9a)

Solutions

  1. Restore the project entry to a full object with at least 'root' and project metadata.
  2. Remove the invalid entry entirely if the project no longer exists.
  3. Re-run `ng generate` / restore angular.json from version control to repair merge-damaged entries.

Example fix

// before (angular.json)
"projects": { "my-app": null }
// after
"projects": { "my-app": { "root": "projects/my-app", "projectType": "application" } }
Defensive patterns

Strategy: type-guard

Validate before calling

const json = require('./angular.json');
for (const [name, value] of Object.entries(json.projects ?? {})) {
  if (typeof value !== 'object' || value === null || Array.isArray(value)) {
    throw new Error(`Project '${name}' in angular.json must be an object, got: ${JSON.stringify(value)}`);
  }
}

Type guard

function isValidProject(v) {
  return typeof v === 'object' && v !== null && !Array.isArray(v);
}

Prevention

When it happens

Trigger: parseProjectsObject iterates projects entries and finds a value that is a string, number, array, boolean, or null instead of an object (e.g. "projects": { "my-app": null }).

Common situations: Merge conflicts in angular.json leaving corrupt project entries; scripts regenerating angular.json writing placeholders; accidental deletion of a project's body leaving an empty/null value.

Related errors


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