vercel/turborepo · error · Error

Unable to fetch the latest version of ${packageName}

Error message

Unable to fetch the latest version of ${packageName}

What it means

`turbo-codemod migrate` resolves the target turbo version by fetching package metadata from the npm registry (`${registry}/turbo`, where registry comes from npm_config_registry or defaults to registry.npmjs.org). Any failure — network error, DNS failure, or non-2xx HTTP status — is wrapped in this Error. Note the fetch happens before the `--to` check, so even an explicit `--to <version>` requires registry access.

Source

Thrown at packages/turbo-codemod/src/commands/migrate/steps/get-latest-version.ts:24

  "dist-tags": {
    latest: string;
    [key: string]: string;
  };
  versions: Record<string, { name: string; version: string }>;
}

async function getPackageDetails({ packageName }: { packageName: string }) {
  const registry =
    process.env.npm_config_registry?.replace(/\/$/, "") || DEFAULT_REGISTRY;

  try {
    const response = await fetch(`${registry}/${packageName}`);
    if (!response.ok) {
      throw new Error(`HTTP ${response.status}`);
    }
    return (await response.json()) as PackageDetailsResponse;
  } catch (err) {
    throw new Error(`Unable to fetch the latest version of ${packageName}`);
  }
}

export async function getLatestVersion({
  to
}: MigrateCommandOptions): Promise<string | undefined> {
  const packageDetails = await getPackageDetails({ packageName: "turbo" });
  const { "dist-tags": tags, versions } = packageDetails;

  if (to) {
    // If 'to' is a dist-tag (e.g. "latest", "canary"), resolve to the concrete version
    if (tags[to]) {
      return tags[to];
    }
    if (to in versions) {
      return to;
    }
    throw new Error(`turbo@${to} does not exist`);

View on GitHub (pinned to 9f94a7d215)

Solutions

  1. Verify registry connectivity the same way the codemod does: `npm view turbo version` from the same shell
  2. If npm_config_registry points at a private registry, ensure it proxies the npmjs group (including the `turbo` package) or override it for the run: `npm_config_registry=https://registry.npmjs.org npx @turbo/codemod migrate`
  3. Configure proxy env vars (HTTPS_PROXY/HTTP_PROXY) so fetch can traverse the corporate proxy, then retry
  4. On flaky networks, simply retry the codemod — it is idempotent with respect to the registry query

Example fix

# before
npx @turbo/codemod migrate   # fails behind private registry
# after
npm_config_registry=https://registry.npmjs.org npx @turbo/codemod migrate
Defensive patterns

Strategy: retry

Validate before calling

async function registryServesTurbo(registry = process.env.npm_config_registry ?? 'https://registry.npmjs.org'): Promise<boolean> {
  try {
    const res = await fetch(`${registry.replace(/\/$/, '')}/turbo`, { method: 'GET' });
    return res.ok;
  } catch {
    return false;
  }
}
// run before turbo-codemod migrate; if false, fix registry/proxy first

Try / catch

async function migrateWithRetry(opts, attempts = 3) {
  for (let i = 0; i < attempts; i++) {
    try {
      return await runMigrate(opts);
    } catch (err) {
      if (err instanceof Error && /Unable to fetch the latest version/.test(err.message) && i < attempts - 1) {
        await new Promise((r) => setTimeout(r, 2 ** i * 500)); // backoff, then retry
        continue;
      }
      throw err;
    }
  }
}

Prevention

When it happens

Trigger: getPackageDetails' fetch throwing or returning !response.ok: offline machine, corporate proxy/firewall blocking registry.npmjs.org, npm_config_registry pointing at a private registry (Artifactory/Verdaccio) that lacks the `turbo` package metadata, or a registry 5xx/404.

Common situations: Air-gapped or proxied CI environments; private registries that don't proxy npmjs; HTTP__PROXY/HTTPS_PROXY env vars not visible to the codemod process; transient registry outages.

Related errors


AI-assisted analysis of vercel/turborepo@9f94a7d215 (2026-08-16). Data as JSON: /api/errors/7637d1ba8cf76a74. Report an issue: GitHub.