Skip to content

fix(@angular/cli): explain how to pick a project when a schematic cannot determine one - #34481

Open
thekhegay wants to merge 2 commits into
angular:mainfrom
thekhegay:cli-25402-project-pick
Open

thekhegay wants to merge 2 commits into
angular:mainfrom
thekhegay:cli-25402-project-pick

Conversation

@thekhegay

@thekhegay thekhegay commented Oct 22, 2026 •

Copy link
Copy Markdown
Contributor

PR Checklist

PR Type

  • Bugfix
  • Feature
  • Code style update (formatting, local variables)
  • Refactoring (no functional changes, no api changes)
  • Build related changes
  • CI related changes
  • Documentation content changes
  • Other... Please describe:

What is the current behavior?

Issue Number: #25402

My library ngwr keeps lib and showcase under projects/ with no root project, and ng g c foo from workspace root on 22.2.3 gives:

Schematic input does not validate against the Schema: {"name":"foo"}
Errors:

  Data path "" must have required property 'project'.

projectName smart default comes from getProjectByCwd(), it returns nothing when cwd is outside every project or inside two projects with same root, so project stays empty and ajv error goes to user as is
Architect commands already explain this with Cannot determine project for command, schematics didnt

What is the new behavior?

When schematic fails because required project is missing and CLI could not resolve it, error says what to do, as Alan suggested in issue:

Cannot determine project for command.
This is a multi-project workspace and the current working directory is not inside a single project. Use the "--project" option to specify a project or change the current working directory to a project directory.

Available projects are:
- lib
- showcase

Workspace with no projects gets This workspace does not contain any projects. Run "ng generate application" or "ng generate library" to create one. instead of empty list
Any other validation error is printed same as before

New schematics-command-module_spec.ts runs real workflow with small local collection that requires project, both cases fail on main
Also added ng generate component to project-cannot-be-determined-by-cwd.ts e2e, it already sets up two apps without root project and prints same ajv error on main

Does this PR introduce a breaking change?

  • Yes
  • No

Other information

Check sits in catch of runSchematic because project can also come from schematics options in angular.json, and validation is only place that knows it is really missing. Can move it before workflow runs, like getProjectNamesByTarget does for architect, if you prefer that
Built CLI from this branch and ran ng g c foo --dry-run at ngwr root, it prints message above, and with --project showcase or from projects/showcase it works as before

closes #25402

…not determine one

when project can't be resolved from cwd, like at root of workspace with no root project, schematics fail with raw `Data path "" must have required property 'project'` from schema validation
now that error is replaced with message that says to pass `--project` or cd into project and lists available projects like architect commands do, empty workspace gets hint to generate application or libary first

Fixes angular#25402

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request improves error messages when running schematics that require a project in a multi-project workspace (or a workspace with no projects) where the project cannot be determined from the current working directory. It adds clear guidance on using the --project option and lists available projects, supported by new unit and end-to-end tests. The feedback suggests guarding the cleanup in afterAll within the unit tests to prevent a secondary TypeError if beforeAll fails and root is undefined.

Comment thread packages/angular/cli/src/command-builder/schematics-command-module_spec.ts Outdated

@alan-agius4 alan-agius4 left a comment •

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for looking into this. However, intercepting SchemaValidationException in the catch block and matching raw AJV error properties for missingProperty === 'project' is pretty brittle:

  1. Because getMissingProjectMessage replaces the entire error message when error.errors.some(...) matches project, any other schema validation errors from the same run (such as invalid flag values or other missing required properties) are completely swallowed.
  2. It assumes that any top-level required project property in any schematic (including third-party schematics or nested schematics called via externalSchematic) uses "$default": { "$source": "projectName" }.
  3. Because this only runs after prompt evaluation and schema validation fail, running ng g c interactively in a multi-project workspace will first prompt the user for the component name and only fail with the missing project error after they answer.
  4. The E2E test addition in project-cannot-be-determined-by-cwd.ts is good, but the unit test in schematics-command-module_spec.ts is overly complex: it scaffolds a fake schematic collection on disk (using os.tmpdir() instead of process.env['TEST_TMPDIR'], which breaks Bazel sandboxing rules), spins up a full NodeWorkflow, and implicitly relies on process.cwd() not falling under the temp workspace.basePath.

If we want to handle missing projectName smart defaults cleanly, this should be tied to the projectName smart default / schema option handling itself rather than scraping AJV validation errors in catch.

@alan-agius4 alan-agius4 added the action: cleanup The PR is in need of cleanup, either due to needing a rebase or in response to comments from reviews label Oct 22, 2026
…tic cannot determine one

Co-authored-by: Alan Agius <alanagius@google.com>
@thekhegay

Copy link
Copy Markdown
Contributor Author

Thanks for catch! Reworked it in 061e5c5

  1. catch is back to plain err.message, nothing reads or replaces ajv errors anymore, once project is known every validation error comes out as before, e2e checks it with invalid --selector and project from angular.json schematics
    if project is missing as well project message comes first, ajv stops at first error anyway so main also showed one error at time
  2. check reads own schema of each schematic it runs for, nested externalSchematic ones too, and fires only for top-level option that is in required, has $default: { $source: 'projectName' }, has no x-prompt and still has no value after angular.json defaults merge, anything else like third-party project without that default keeps raw error, message uses that option's name for flag
  3. it is now option transform registered next to addSmartDefaultProvider('projectName', ...), it runs right after angular.json schematics defaults merge and before validateOptionsWithSchema, so before smart defaults and prompts, ng g c in multi-project root fails right away without asking for name, e2e runs it with NG_FORCE_TTY=1 and checks name prompt never shows
  4. spec now just calls exported getMissingProjectMessage with in-memory schema and AngularWorkspace, nothing on disk and no workflow

Didnt put it inside projectName provider itself, registry calls provider even when option already has value and passes only $default object, so provider has no way to tell if option is required or missing

@thekhegay
thekhegay requested a review from alan-agius4 October 22, 2026 11:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

action: cleanup The PR is in need of cleanup, either due to needing a rebase or in response to comments from reviews area: @angular/cli

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Data path "" must have required property 'project'.

2 participants