vercel/turborepo · error · Error

Unable to fetch the latest version of

Error message

Unable to fetch the latest version of ${packageName}

What it means

The turbo-codemod migrate command queries the npm registry for turbo metadata to learn the latest version. getPackageDetails fetches `${registry}/turbo`, where the registry comes from npm_config_registry or defaults to npmjs. It throws this Error when the request fails, returns a non-OK HTTP status, or the body cannot be parsed as JSON.

Solutions

  1. Verify connectivity: curl https://registry.npmjs.org/turbo or npm ping
  2. Fix or unset npm_config_registry so it points to a registry that serves turbo metadata
  3. Configure proxy settings (HTTPS_PROXY) or connect to a network that allows registry access
  4. Retry the migrate command; registry requests are often transient failures

Example fix

# before: broken registry override
npm_config_registry=https://registry.internal.example npm exec @turbo/codemod migrate
# after: default registry
npm exec @turbo/codemod migrate
Defensive patterns

Strategy: retry

Validate before calling

// verify registry reachability for turbo metadata before running the codemod
const registry = (process.env.npm_config_registry ?? "https://registry.npmjs.org").replace(/\/$/, "");
const res = await fetch(`${registry}/turbo`, { method: "HEAD" });
if (!res.ok) {
  throw new Error(`Registry not reachable for turbo: HTTP ${res.status}`);
}

Try / catch

async function fetchPackageDetailsWithRetry(url: string, attempts = 3) {
  for (let i = 0; i < attempts; i++) {
    try {
      const res = await fetch(url);
      if (res.ok) return await res.json();
      if (res.status >= 500 && i < attempts - 1) continue; // retry server errors
      throw new Error(`HTTP ${res.status}`);
    } catch (err) {
      if (i === attempts - 1) throw new Error("Unable to fetch the latest version of turbo");
      await new Promise((r) => setTimeout(r, 2 ** i * 500)); // backoff
    }
  }
}

Prevention

When it happens

Trigger: No network access, DNS failure, or a corporate proxy blocks the registry. A custom npm_config_registry value points to an unreachable or private registry that does not serve the turbo package. The registry returns HTTP 404 or 5xx. response.json() fails because the response is not JSON.

Common situations: Running @turbo/codemod migrate behind a corporate proxy or firewall. A custom Artifactory or Verdaccio mirror that lacks the turbo package. A typo in npm_config_registry. Transient network outage or registry downtime.

Related errors


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

Appendix: 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 f9245100cf)