How to Fix: The upgrade codemod always requests registry.npmjs.org, even though I have another registry configured
The Next.js upgrade codemod can fail in locked-down or private package environments because it always talks to registry.npmjs.org when checking versions, even if your project, user, or CI setup is configured to use a different npm registry. If your network blocks the public registry or your organization mirrors packages through Artifactory, Nexus, Verdaccio, or GitHub Packages, the codemod breaks before the upgrade even starts.
Table of Contents
Understanding the Root Cause
The bug comes from the codemod implementation using a hardcoded request path to the public npm registry instead of resolving the registry from your existing package manager configuration.
In practice, developers often configure registries through one or more of these sources:
- project-level .npmrc
- user-level ~/.npmrc
- NPM_CONFIG_REGISTRY environment variable
- package-manager-specific config for pnpm or Yarn
- scoped registry entries such as @my-company:registry=…
The codemod should ideally ask the active package manager which registry to use, or read the resolved npm config. Instead, it directly requests metadata from registry.npmjs.org. That creates two technical problems:
- Configuration is ignored, so custom registry settings never take effect.
- Network assumptions are wrong, so corporate firewalls, air-gapped networks, or mirrored registries cause immediate lookup failures.
This is why the issue is reproducible simply by blocking access to the public npm registry while keeping a private registry configured and available. The package installation path may work fine, but the version discovery logic inside the codemod still fails.
Step-by-Step Solution
There are two practical ways to solve this: a local workaround you can use immediately, and the correct upstream code fix if you want to patch the tool itself or contribute a pull request.
1. Confirm your active registry
Before patching anything, verify what registry your environment is actually using.
npm config get registry
pnpm config get registry
yarn config get npmRegistryServer
If your output is not the public npm registry, your environment is configured correctly and the codemod is the component bypassing that config.
2. Reproduce the failure clearly
Run the upgrade command in the same shell where your registry is configured.
npx @next/codemod@latest upgrade latest
If your environment blocks public npm access, the command typically fails during the metadata lookup phase rather than during package installation.
3. Apply the correct code fix
The proper fix is to replace the hardcoded registry URL with one resolved from npm configuration. A robust implementation should:
- check NPM_CONFIG_REGISTRY
- fall back to npm config get registry
- normalize trailing slashes
- build the package metadata URL from that resolved registry
A simple Node.js approach looks like this:
import { execSync } from 'node:child_process'
function getRegistry() {
if (process.env.NPM_CONFIG_REGISTRY) {
return process.env.NPM_CONFIG_REGISTRY.replace(/\/$/, '')
}
try {
const registry = execSync('npm config get registry', { encoding: 'utf8' }).trim()
return registry.replace(/\/$/, '')
} catch {
return 'https://registry.npmjs.org'
}
}
const registry = getRegistry()
const packageUrl = `${registry}/next`
If you are editing the codemod source, update the version-fetching logic so the request target is built from getRegistry() instead of a fixed https://registry.npmjs.org string.
4. Improve support for scoped or enterprise registries
Some organizations proxy all packages through a private registry, while others define scope-specific registries. If the tool needs to fetch metadata for packages under a scope, support both global and scoped resolution.
npm config get @my-company:registry
npm config get registry
If the package is unscoped, the default registry usually applies. For internal packages, scope-specific values may be required.
5. Use a temporary workaround if you cannot patch the codemod
If you need to run the upgrade immediately, force the shell environment so the codemod sees the intended registry if it respects process configuration anywhere in its execution path.
export NPM_CONFIG_REGISTRY=https://your-registry.example.com/
npx @next/codemod@latest upgrade latest
On Windows PowerShell:
$env:NPM_CONFIG_REGISTRY="https://your-registry.example.com/"
npx @next/codemod@latest upgrade latest
If the codemod still hardcodes the public URL internally, this may not fully fix the issue, but it is still worth testing because some dependent package manager operations may start using the right registry.
6. Verify the fix end-to-end
After patching, test in an environment where registry.npmjs.org is unreachable but your private registry is available.
npm config get registry
node -e "console.log(process.env.NPM_CONFIG_REGISTRY || 'no env override')"
npx @next/codemod@latest upgrade latest
Success means the codemod resolves package metadata without requiring direct access to the public registry.
7. Prepare an upstream contribution
If you want to submit a fix to Next.js, keep the patch focused:
- replace hardcoded registry usage
- preserve fallback to npmjs for backward compatibility
- add tests for custom registry resolution
- document behavior for CI and enterprise environments
Reference the original source location through the affected upgrade.ts implementation.
Common Edge Cases
1. Scoped packages use a different registry
A company may configure @scope:registry separately from the default registry. If the codemod later expands to check scoped dependencies, a default-only lookup will still be incomplete.
2. Authentication is required for metadata requests
Some private registries require tokens even for package metadata. In those cases, using the correct registry URL is not enough; the request layer must also respect .npmrc auth settings or use the package manager to fetch metadata.
3. Trailing slash bugs
Registries may be configured with or without a trailing slash. If the URL builder does not normalize this, requests can become malformed with duplicated slashes or missing separators.
4. CI uses a different registry than local development
Many teams rely on environment variables in CI while developers use ~/.npmrc. A fix that only reads one source can still fail in pipelines.
5. Yarn or pnpm projects do not always mirror npm behavior exactly
Even though npm registry settings are often compatible, some setups rely on package-manager-specific configuration. The safest long-term implementation is to resolve the active package manager first, then query its effective registry settings.
6. Offline mirrors and proxy registries may cache selectively
If your private registry proxies npm but does not yet contain the required metadata, you may still see failures until the cache is populated or upstream access is allowed through the mirror.
FAQ
Why does package installation work, but the Next.js codemod still fails?
Because package installation usually goes through your configured package manager, which respects your registry settings. The codemod’s version lookup logic is making its own direct request to registry.npmjs.org, bypassing that configuration.
Can I fix this only with .npmrc?
Not if the tool is truly hardcoding the registry URL. A correct .npmrc helps the package manager, but it cannot override application code that explicitly calls a different host.
What is the best permanent fix for maintainers?
The best fix is to stop hardcoding the registry and instead resolve it from the active configuration source, with a safe fallback to npmjs. Even better, the codemod can delegate metadata resolution to the package manager or a shared utility that already understands npm config, auth, and enterprise registry behavior.
If you are maintaining internal tooling around Next.js upgrades, treat this bug as a reminder that registry resolution is infrastructure-sensitive logic. Any tool that fetches package metadata should use the same configuration path as the installer, otherwise upgrades will fail in exactly the environments that depend most on private package infrastructure.