`ng update` fails for custom schematic with “An unhandled exception occurred: Cannot find module”

🐞 Bug report

Command

  • new
  • build
  • serve
  • test
  • e2e
  • generate
  • add
  • update
  • lint
  • extract-i18n
  • run
  • config
  • help
  • version
  • doc

Is this a regression?

Yes, the previous version in which this bug was not present was: ~10.2.1 (and possibly anything less than 11.1.4)

Description

When running ng update my-package the process fails with the following error (full stacktrace included below):

An unhandled exception occurred: Cannot find module 'my-package'

Our package depends on Angular 10.x, so this is being run in an Angular 10 workspace.

I believe this is a bug in the latest Angular CLI because:

  • We tested this update command when we released the new version of our schematics package on 2021-01-29 and it worked back then, but now it does not (with no changes to our package)
  • When running ng update the Angular CLI will check the version of the CLI installed locally and if it is not the latest version then it will install the latest version in a tmp dir and use that to run the update
  • A new version of the CLI has been released since we last saw this working, so that’s the only thing that’s changed
  • If you run NG_DISABLE_VERSION_CHECK=1 ng update ... to disable the ‘use latest CLI’ behaviour and instead use the locally-installed v.10 of the CLI, then the migration completes successfully.

🔬 Minimal Reproduction

  • Create a custom schematic and publish two versions, with some migrations
  • Install the old version of the package containing the schematic in an Angular 10 project
  • Run ng update custom-schematic-package-name

🔥 Exception or Error


An unhandled exception occurred: Cannot find module 'my-package'
Require stack:
- /private/var/folders/4y/f65lmpz57ls14s3sxyd_r7tw0000gp/T/angular-cli-packages-ueI9pk/node_modules/@angular/cli/commands/update-impl.js
- /private/var/folders/4y/f65lmpz57ls14s3sxyd_r7tw0000gp/T/angular-cli-packages-ueI9pk/node_modules/@angular-devkit/schematics/tools/export-ref.js
- /private/var/folders/4y/f65lmpz57ls14s3sxyd_r7tw0000gp/T/angular-cli-packages-ueI9pk/node_modules/@angular-devkit/schematics/tools/index.js
- /private/var/folders/4y/f65lmpz57ls14s3sxyd_r7tw0000gp/T/angular-cli-packages-ueI9pk/node_modules/@angular/cli/utilities/json-schema.js
- /private/var/folders/4y/f65lmpz57ls14s3sxyd_r7tw0000gp/T/angular-cli-packages-ueI9pk/node_modules/@angular/cli/models/command-runner.js
- /private/var/folders/4y/f65lmpz57ls14s3sxyd_r7tw0000gp/T/angular-cli-packages-ueI9pk/node_modules/@angular/cli/lib/cli/index.js
- /private/var/folders/4y/f65lmpz57ls14s3sxyd_r7tw0000gp/T/angular-cli-packages-ueI9pk/node_modules/@angular/cli/lib/init.js
- /private/var/folders/4y/f65lmpz57ls14s3sxyd_r7tw0000gp/T/angular-cli-packages-ueI9pk/node_modules/@angular/cli/bin/ng
    at Function.Module._resolveFilename (internal/modules/cjs/loader.js:957:15)
    at Function.resolve (internal/modules/cjs/helpers.js:83:19)
    at UpdateCommand.run (/private/var/folders/4y/f65lmpz57ls14s3sxyd_r7tw0000gp/T/angular-cli-packages-ueI9pk/node_modules/@angular/cli/commands/update-impl.js:493:45)
    at processTicksAndRejections (internal/process/task_queues.js:97:5)
    at async UpdateCommand.validateAndRun (/private/var/folders/4y/f65lmpz57ls14s3sxyd_r7tw0000gp/T/angular-cli-packages-ueI9pk/node_modules/@angular/cli/models/command.js:139:28)
    at async Object.runCommand (/private/var/folders/4y/f65lmpz57ls14s3sxyd_r7tw0000gp/T/angular-cli-packages-ueI9pk/node_modules/@angular/cli/models/command-runner.js:204:24)
    at async default_1 (/private/var/folders/4y/f65lmpz57ls14s3sxyd_r7tw0000gp/T/angular-cli-packages-ueI9pk/node_modules/@angular/cli/lib/cli/index.js:80:31)

🌍 Your Environment


$ ng version
Your global Angular CLI version (11.1.1) is greater than your local version (10.2.2). The local Angular CLI version is used.

To disable this warning use "ng config -g cli.warnings.versionMismatch false".

     _                      _                 ____ _     ___
    / \   _ __   __ _ _   _| | __ _ _ __     / ___| |   |_ _|
   / △ \ | '_ \ / _` | | | | |/ _` | '__|   | |   | |    | |
  / ___ \| | | | (_| | |_| | | (_| | |      | |___| |___ | |
 /_/   \_\_| |_|\__, |\__,_|_|\__,_|_|       \____|_____|___|
                |___/


Angular CLI: 10.2.2
Node: 12.16.3
OS: darwin x64

Angular: 10.1.5
... animations, common, compiler, core, forms, localize
... platform-browser, platform-browser-dynamic, router
Ivy Workspace: Yes

Package                         Version
---------------------------------------------------------
@angular-devkit/architect       0.1002.2
@angular-devkit/build-angular   0.1002.2
@angular-devkit/core            10.2.2
@angular-devkit/schematics      10.2.2
@angular/cdk                    10.1.3
@angular/cli                    10.2.2
@angular/compiler-cli           10.2.4
@schematics/angular             10.2.2
@schematics/update              0.1002.2
rxjs                            6.6.2
typescript                      4.0.7

1 possible answer(s) on “`ng update` fails for custom schematic with “An unhandled exception occurred: Cannot find module”

  1. I see that the error messages have been updated in v12 which is nice but unfortunately didn’t really help resolve the problem. But I do have more information.

    It appears that the package that is causing the error to be thrown doesn’t contain an entry file (it’s a package that only contains schematics, so one wasn’t needed) and wasn’t being detected as a package. I’m fairly sure this isn’t a change in the behaviour of require.resolve since I used the same node version for all of my tests.

    Adding a "main" entry in the package.json pointing to a dummy index.js file to the published package seems to have fixed the problem (at least in future versions – the already published packages are still broken).

    I still believe this is a regression bug, as the same package (without the entry file) has worked with all previous Angular CLI versions.