withastro/astro · error · Error
Unable to resolve "${packageInfo.name}"
Error message
Unable to resolve "${packageInfo.name}" What it means
Thrown by resolveTargetVersion in the upgrade tool when the npm registry responds with HTTP >= 400 to a packument (full package metadata) request for the package being upgraded. The upgrade CLI fetches `${registry}/${name}` to read dist-tags, so any 4xx/5xx (404 not found, registry outage, auth required) aborts the version resolution. It is a generic Error, not an AstroError, so it carries no code or hint.
Source
Thrown at packages/upgrade/src/actions/verify.ts:147
return false;
}
for (const packageInfo of ctx.packages) {
if (!packageInfo.targetVersion) {
return false;
}
}
return true;
}
export async function resolveTargetVersion(
packageInfo: PackageInfo,
registry: string,
): Promise<void> {
const packageMetadata = await fetch(`${registry}/${packageInfo.name}`, {
headers: { accept: 'application/vnd.npm.install-v1+json' },
});
if (packageMetadata.status >= 400) {
throw new Error(`Unable to resolve "${packageInfo.name}"`);
}
const { 'dist-tags': distTags } = await packageMetadata.json();
let version = distTags[packageInfo.targetVersion];
if (version) {
const currentCoerced = semverCoerce(packageInfo.currentVersion);
const targetParsed = semverParse(version);
// If the dist-tag points to a version older than the installed one, fall back to latest.
if (currentCoerced && targetParsed && semverGt(currentCoerced, targetParsed)) {
packageInfo.targetVersion = 'latest';
version = distTags.latest;
} else {
packageInfo.tag = packageInfo.targetVersion;
packageInfo.targetVersion = version;
}
} else {
packageInfo.targetVersion = 'latest';
version = distTags.latest;
}View on GitHub (pinned to d081033d5f)
Solutions
- Verify the package exists on your registry: `npm view <name>` or open `${registry}/${name}` in a browser and confirm a 200 response with dist-tags.
- If using a private/custom registry, ensure npm config (`.npmrc` NPM_CONFIG_REGISTRY, or the registry argument passed to the action) points to a registry that actually hosts the package and that auth is configured.
- Check connectivity/proxy: run `curl -I ${registry}/${name}` from the same environment and confirm it is not a 401/403/404/5xx.
- Confirm the package name spelling and scope (e.g. `@astrojs/check`, not `astrojs/check`).
Example fix
// before
const packageMetadata = await fetch(`${registry}/${packageInfo.name}`, {
headers: { accept: 'application/vnd.npm.install-v1+json' },
});
if (packageMetadata.status >= 400) {
throw new Error(`Unable to resolve "${packageInfo.name}"`);
}
// after — surface the HTTP status so the failure is debuggable
if (packageMetadata.status >= 400) {
throw new Error(
`Unable to resolve "${packageInfo.name}" (registry ${registry} returned ${packageMetadata.status})`,
);
} Defensive patterns
Strategy: retry
Validate before calling
// Validate the package is resolvable before calling resolveTargetVersion
import { fetch } from 'undici';
async function packageResolves(registry: string, name: string): Promise<boolean> {
const res = await fetch(`${registry}/${encodeURIComponent(name)}`);
return res.status < 400;
}
// call before resolveTargetVersion:
if (!(await packageResolves(registry, packageInfo.name))) {
// surface a user-facing message instead of letting the tool throw
} Type guard
function isValidPackageName(name: string): boolean {
// npm scope/name rules
return /^(?:@[a-z0-9-~][a-z0-9-._~]*\/)?[a-z0-9-~][a-z0-9-._~]*$/.test(name);
} Try / catch
try {
await resolveTargetVersion(packageInfo, registry);
} catch (e) {
if (e instanceof Error && e.message.startsWith('Unable to resolve')) {
// retry once, then report a registry/connectivity problem to the user
} else throw e;
} Prevention
- Pin the registry explicitly (NPM_CONFIG_REGISTRY or the action's registry arg) rather than relying on ambient config.
- Validate package names before constructing PackageInfo.
- Run `npm view <name>` as a preflight in CI before invoking the upgrade tool.
- Ensure auth tokens for private registries are present in the environment.
When it happens
Trigger: Calling the upgrade command against a package name that does not exist on the configured registry; using a custom/private registry that requires auth (returns 401/403); the registry host is down or returns 5xx; the packageInfo.name is mistyped or scoped incorrectly (e.g. missing @scope/).
Common situations: A developer runs `astro upgrade` or `astro upgrade --package <name>` while offline or behind a corporate proxy; using an internal Verdaccio/Nexus registry that needs a token; the package was renamed/deprecated on npm; a typo in a manually constructed PackageInfo.
Related errors
- CannotFetchFontFile
- Unable to fetch ${integration}. Does the package exist?
- Failed to fetch latest Astro version
- Template ${tmpl} does not exist!
- Unable to download template ${tmpl}
AI-assisted analysis of withastro/astro@d081033d5f (2026-08-12).
Data as JSON: /api/errors/438bda488a885dc4.
Report an issue: GitHub.