yarnpkg/yarn · error · MessageError
malformedRegistryResponse
Error message
malformedRegistryResponse
What it means
findVersionInRegistryResponse() throws when body lacks dist-tags OR body lacks versions entirely. The registry response is structurally incomplete and cannot be used for resolution. This is distinct from error 93 which checks for an empty versions object.
Source
Thrown at src/resolvers/registries/npm-resolver.js:44
'dist-tags': {[key: string]: string},
};
export default class NpmResolver extends RegistryResolver {
static registry = NPM_REGISTRY_ID;
static async findVersionInRegistryResponse(
config: Config,
name: string,
range: string,
body: RegistryResponse,
request: ?PackageRequest,
): Promise<Manifest> {
if (body.versions && Object.keys(body.versions).length === 0) {
throw new MessageError(config.reporter.lang('registryNoVersions', body.name));
}
if (!body['dist-tags'] || !body.versions) {
throw new MessageError(config.reporter.lang('malformedRegistryResponse', name));
}
if (range in body['dist-tags']) {
range = body['dist-tags'][range];
}
// If the latest tag in the registry satisfies the requested range, then use that.
// Otherwise we will fall back to semver maxSatisfying.
// This mimics logic in NPM. See issue #3560
const latestVersion = body['dist-tags'] ? body['dist-tags'].latest : undefined;
if (latestVersion && semver.satisfies(latestVersion, range)) {
return body.versions[latestVersion];
}
const satisfied = await config.resolveConstraints(Object.keys(body.versions), range);
if (satisfied) {
return body.versions[satisfied];
} else if (request && !config.nonInteractive) {View on GitHub (pinned to c2dda503f3)
Solutions
- Switch to the canonical npm registry to confirm the package exists there
- Verify the registry endpoint returns the standard packument format (dist-tags + versions)
- Check for proxy/CDN corruption altering the response body
- Contact the registry provider if the format is non-standard
Defensive patterns
Strategy: validation
Validate before calling
function isWellFormedPackument(body: object): boolean {
return !!body['dist-tags'] && !!body.versions;
} Type guard
function isCompleteRegistryResponse(body: object): boolean {
return 'dist-tags' in body && 'versions' in body;
} Try / catch
try {
const manifest = await NpmResolver.findVersionInRegistryResponse(config, name, range, body);
} catch (e) {
if (e.message.includes('malformedRegistryResponse')) {
// retry against the canonical npm registry
}
} Prevention
- Use the canonical npm registry to confirm packument integrity
- Avoid custom registries that return non-standard formats
- Validate proxy responses for field completeness
When it happens
Trigger: A registry returns JSON missing the dist-tags field or the versions field. Checked immediately after the empty-versions guard.
Common situations: Corrupt or non-compliant registry proxies; custom registries returning non-standard packuments; tarball-only or error endpoints that still return 200.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- invalidAccess
- missingAddDependencies
- Unexpected audit response (Invalid JSON): ${response}
- Unexpected audit response (Missing Metadata): ${JSON.stringi
- Name should not start with "/", got "${str}"
AI-assisted analysis of yarnpkg/yarn@c2dda503f3 (2026-08-13).
Data as JSON: /api/errors/e5623116965d244b.
Report an issue: GitHub.