Skip to content

ng update does not work. #33500

Closed as not planned
Closed as not planned

Description

@parapada73

Command

update

Is this a regression?

  • Yes, this behavior used to work in the previous version

The previous version in which this bug was not present was

No response

Description

The image below shows the results of running npm outdate and ng update.
Both package.json and package-lock.json are specified as 22.0.4. However, the output of ng update indicates that there are no updates.

It seems the ng update command is behaving differently than in previous versions.

Image

Minimal Reproduction

npm outdate
ng update --verbose

Exception or Error


Your Environment

Angular CLI       : 22.0.4
Angular           : 22.0.4
Node.js           : 24.18.0
Package Manager   : npm 11.18.0
Operating System  : linux x64

┌───────────────────────────┬───────────────────┬───────────────────┐
│ Package                   │ Installed Version │ Requested Version │
├───────────────────────────┼───────────────────┼───────────────────┤
│ @angular/build            │ 22.0.4            │ ^22.0.4           │
│ @angular/cli              │ 22.0.4            │ ^22.0.4           │
│ @angular/common           │ 22.0.4            │ ^22.0.4           │
│ @angular/compiler         │ 22.0.4            │ ^22.0.4           │
│ @angular/compiler-cli     │ 22.0.4            │ ^22.0.4           │
│ @angular/core             │ 22.0.4            │ ^22.0.4           │
│ @angular/forms            │ 22.0.4            │ ^22.0.4           │
│ @angular/platform-browser │ 22.0.4            │ ^22.0.4           │
│ @angular/router           │ 22.0.4            │ ^22.0.4           │
│ rxjs                      │ 7.8.2             │ ^7.8.2            │
│ typescript                │ 6.0.3             │ ^6.0.3            │
└───────────────────────────┴───────────────────┴───────────────────┘

Anything else relevant?

No response

Activity

  1. added this to the needsTriage milestone on Jul 1, 2026
  2. alan-agius4 commented on Jul 2, 2026

    @alan-agius4
    Collaborator

    Hi @parapada73,

    This behavior is working as intended. ng update and npm outdated operate differently:

    • ng update checks the version ranges specified in package.json against the npm registry to determine if a newer version exists.
    • npm outdated checks the actual versions currently installed in node_modules (or recorded in package-lock.json) against the npm registry.

    Because your package.json already specifies a version that matches 22.0.5, ng update correctly reports that no update is required. If node_modules is out of sync with package.json, deleting the lockfile and running npm install will bring your installed packages up to date.

  3. parapada73 commented on Jul 15, 2026

    @parapada73
    Author

    Hi @parapada73,

    This behavior is working as intended. ng update and npm outdated operate differently:

    • ng update checks the version ranges specified in package.json against the npm registry to determine if a newer version exists.
    • npm outdated checks the actual versions currently installed in node_modules (or recorded in package-lock.json) against the npm registry.

    Because your package.json already specifies a version that matches 22.0.5, ng update correctly reports that no update is required. If node_modules is out of sync with package.json, deleting the lockfile and running npm install will bring your installed packages up to date.

    Hi, @alan-agius4 .
    Both package.json and package-lock.json were 22.0.4. This can be confirmed by running npm outdate and ng version.
    Previously, running ng update would output a list of items to be updated. Currently, no list is displayed.

  4. glenstaes commented on Jul 30, 2026

    @glenstaes

    I'm experiencing the same as what is reported here, with the extra caveat that I always removed the carets and tildes in package.json.

    Within the company that I work for, we have this policy of only updating dependencies when necessary. This means installing patches only when it actually fixes an issue we run into, or a vulnerability has been found. In the past, we also had dependencies not fully adhering to semver, thus introducing breaking changes in a minor or even patch versions. It also made sure that all developers within the team were using the exact same version of the dependencies.

    In the past, the ng update command was the way I updated my Angular dependencies. So I am absolutely 100% certain that ng update listed new versions (major, minor and patch) even though my package.json had no carets or tildes. Right now I'm trying to update to version 22.1.0 and this is the output:

    Using package manager: npm
    Collecting installed dependencies...
    Found 83 dependencies.
    We analyzed your package.json and everything seems to be in order. Good work!
    

    I have been doing my Angular updates like this for years now, so I'm really really really sure there would have been an entry for updating Angular cli and core to 22.1.0 in the past.

    @alan-agius4 I can understand the reasoning behind your statement:

    "ng update checks the version ranges specified in package.json against the npm registry to determine if a newer version exists."

    I really do. But since OP is not the only one running into this (#33508), I do feel like there must be some kind of regression somewhere.

    For what it's worth, here's my ng version output:

    Angular CLI       : 22.0.1
    Angular           : 22.0.1
    Node.js           : 24.16.0
    Package Manager   : npm 11.13.0
    Operating System  : win32 x64
    
    ┌───────────────────────────────────┬───────────────────┬───────────────────┐
    │ Package                           │ Installed Version │ Requested Version │
    ├───────────────────────────────────┼───────────────────┼───────────────────┤
    │ @angular/animations               │ 22.0.1            │ 22.0.1            │
    │ @angular/build                    │ 22.0.1            │ 22.0.1            │
    │ @angular/cdk                      │ 22.0.1            │ 22.0.1            │
    │ @angular/cli                      │ 22.0.1            │ 22.0.1            │
    │ @angular/common                   │ 22.0.1            │ 22.0.1            │
    │ @angular/compiler                 │ 22.0.1            │ 22.0.1            │
    │ @angular/compiler-cli             │ 22.0.1            │ 22.0.1            │
    │ @angular/core                     │ 22.0.1            │ 22.0.1            │
    │ @angular/flex-layout              │ 15.0.0-beta.42    │ 15.0.0-beta.42    │
    │ @angular/forms                    │ 22.0.1            │ 22.0.1            │
    │ @angular/language-service         │ 22.0.1            │ 22.0.1            │
    │ @angular/material                 │ 22.0.1            │ 22.0.1            │
    │ @angular/material-luxon-adapter   │ 22.0.1            │ 22.0.1            │
    │ @angular/material-moment-adapter  │ 22.0.1            │ 22.0.1            │
    │ @angular/platform-browser         │ 22.0.1            │ 22.0.1            │
    │ @angular/platform-browser-dynamic │ 22.0.1            │ 22.0.1            │
    │ @angular/router                   │ 22.0.1            │ 22.0.1            │
    │ rxjs                              │ 7.8.2             │ 7.8.2             │
    │ typescript                        │ 6.0.3             │ 6.0.3             │
    │ vitest                            │ 4.0.18            │ 4.0.18            │
    └───────────────────────────────────┴───────────────────┴───────────────────┘
    

    I also wanted to be of any help and I found the following in index.ts of the update command schematic:

    if (packages.size === 0) {
          // User ran just `ng update` to see the outdated package list.
          // We must fetch metadata for all npm dependencies to generate the usage message.
          await Promise.all(
            Array.from(npmDeps.keys()).map(async (depName) => {
              await getOrFetchPackageMetadata(depName);
            }),
          );
        } else {
    

    When using ng update to list the possible updates, for all deps the metadata will be fetched and loaded into npmPackageJsonMap.
    Afterwards, this is completely ignored because we are entering this else branch when building PackageInfo for each module:

    } else {
            // If not updating and installed locally, resolve purely locally
            packageInfoMap.set(
              depName,
              _buildLocalPackageInfo(tree, depName, npmDeps, workspaceRoot, logger),
            );
          }
    

    If we were to enter that if-branch instead of the else branch, we would be using the information previously fetched from npm anyway.
    I let Codex run for a while and it confirmed that there's a different output for tags 22.0.0 and 22.0.1 and was able to fix it:


    Result

    Exact source: v22.0.1
    Reproduced bare ng update incorrectly reporting:

    We analyzed your package.json and everything seems to be in order.

    npm outdated simultaneously reported:

    @angular/core 22.0.0 → 22.1.0

    Named ng update @angular/core correctly discovered 22.1.0 and updated package.json.
    After the fix, bare ng update --verbose lists:

    @angular/core 22.0.0 -> 22.1.0 — ng update @angular/core

    Cause

    The comparison with v22.0.0 confirms 4510dae introduced the faulty control flow:

    1. Bare listing leaves packages.size === 0.
    2. Registry metadata is fetched into npmPackageJsonMap.
    3. While building packageInfoMap, installed dependencies have isUpdating === false and a local manifest.
    4. They therefore take _buildLocalPackageInfo(), which sets npmPackageJson to {}.
    5. _usageMessage() has no dist-tags or versions, falls back to the installed version, gets no target, and filters the dependency out.

    v22.0.0 always built package information from the fetched registry metadata.

    Changes

    packages/angular/cli/src/commands/update/schematic/index.ts

    • Captures isListingUpdates as packages.size === 0
    • Updates if (isUpdating || !localPkgJson) { to if (isListingUpdates || isUpdating || !localPkgJson) {
    • Uses cached registry metadata during listing.
    • Preserves local-only resolution for unrelated dependencies in targeted updates.
    • Preserves the existing local fallback when metadata fetching fails.

    I don't agree with the fix Codex suggests, because why would we still need the if-else then, but it does highlight there's a difference between 22.0.0 and 22.0.1.

  5. alan-agius4 commented on Jul 31, 2026

    @alan-agius4
    Collaborator

    @glenstaes, can you please file a new issue, this seems unrelated to the original issue here.

  6. parapada73 commented on Jul 31, 2026

    @parapada73
    Author

    hi @alan-agius4

    I am not the only one experiencing this problem; many people are facing the same issue. I cannot understand closing this issue simply because it was not planned.

  7. glenstaes commented on Jul 31, 2026

    @glenstaes

    @glenstaes, can you please file a new issue, this seems unrelated to the original issue here.

    @alan-agius4 I created #33712

  8. angular-automatic-lock-bot commented on Sep 4, 2026

    @angular-automatic-lock-bot

    This issue has been automatically locked due to inactivity.
    Please file a new issue if you are encountering a similar or related problem.

    Read more about our automatic conversation locking policy.

    This action has been performed automatically by a bot.

  9. locked and limited conversation to collaborators on Sep 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions