From 17b9c95b04e38ba4faac5c12be2c58fa8a32e503 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leosvel=20P=C3=A9rez=20Espinosa?= Date: Thu, 19 Mar 2026 15:29:40 +0100 Subject: [PATCH] fix(core): improve error handling in nx migrate registry fetching - Always use npm for `pack` since only npm supports downloading remote packages (pnpm/yarn/bun pack the local project) - Throw on install fallback failure instead of returning empty object which caused undefined version propagation ("Fetching nx@undefined") - Log registry fetch errors at verbose level for debuggability --- .../nx/src/command-line/migrate/migrate.ts | 20 +++++++++++------- packages/nx/src/utils/package-manager.ts | 21 +++++++------------ 2 files changed, 21 insertions(+), 20 deletions(-) diff --git a/packages/nx/src/command-line/migrate/migrate.ts b/packages/nx/src/command-line/migrate/migrate.ts index 479d153daa48d8..c51dad1b27080a 100644 --- a/packages/nx/src/command-line/migrate/migrate.ts +++ b/packages/nx/src/command-line/migrate/migrate.ts @@ -2,6 +2,7 @@ import * as pc from 'picocolors'; import { exec, execSync, type StdioOptions } from 'child_process'; import { prompt } from 'enquirer'; import { dirname, join } from 'path'; +import { joinPathFragments } from '../../utils/path'; import { clean, coerce, @@ -978,7 +979,10 @@ function createFetcher() { setCache(packageName, resolvedVersion); return getPackageMigrationsUsingRegistry(packageName, resolvedVersion); }) - .catch(() => { + .catch((e) => { + logger.verbose( + `Failed to get migrations from registry for ${packageName}@${packageVersion}: ${e.message}. Falling back to install.` + ); logger.info(`Fetching ${packageName}@${packageVersion}`); return getPackageMigrationsUsingInstall(packageName, packageVersion); @@ -1115,7 +1119,7 @@ async function downloadPackageMigrationsFromRegistry( const migrations = await extractFileFromTarball( join(dir, tarballPath), - join('package', migrationsFilePath), + joinPathFragments('package', migrationsFilePath), join(dir, migrationsFilePath) ).then((path) => readJsonFile(path)); @@ -1148,6 +1152,10 @@ async function getPackageMigrationsUsingInstall( await execAsync(`${pmc.add} ${packageName}@${packageVersion}`, { cwd: dir, + env: { + ...process.env, + npm_config_legacy_peer_deps: 'true', + }, }); const { @@ -1163,11 +1171,9 @@ async function getPackageMigrationsUsingInstall( result = { ...migrations, packageGroup, version: packageJson.version }; } catch (e) { - output.warn({ - title: `Failed to fetch migrations for ${packageName}@${packageVersion}`, - bodyLines: [e.message], - }); - return {}; + throw new Error( + `Failed to fetch migrations for ${packageName}@${packageVersion}: ${e.message}` + ); } finally { await cleanup(); } diff --git a/packages/nx/src/utils/package-manager.ts b/packages/nx/src/utils/package-manager.ts index 614e7e6fa9630d..f522eedaced222 100644 --- a/packages/nx/src/utils/package-manager.ts +++ b/packages/nx/src/utils/package-manager.ts @@ -610,19 +610,14 @@ export async function packageRegistryPack( pkg: string, version: string ): Promise<{ tarballPath: string }> { - let pm = detectPackageManager(); - if (pm === 'yarn' || pm === 'bun') { - /** - * `(p)npm pack` will download a tarball of the specified version, - * whereas `yarn` pack creates a tarball of the active workspace, so it - * does not work for getting the content of a library. - * - * @see https://github.com/nrwl/nx/pull/9667#discussion_r842553994 - * - * bun doesn't currently support pack - */ - pm = 'npm'; - } + /** + * Only `npm pack` supports downloading a tarball of a specified remote + * package. `yarn` packs the active workspace, `pnpm pack` only packs + * the local project, and `bun` doesn't support pack. + * + * @see https://github.com/nrwl/nx/pull/9667#discussion_r842553994 + */ + const pm = 'npm'; const { stdout } = await execAsync(`${pm} pack ${pkg}@${version}`, { cwd,