yarnpkg/yarn · error · Error

Unexpected audit response (Missing Metadata): ${JSON.stringi

Error message

Unexpected audit response (Missing Metadata): ${JSON.stringify(responseJson, null, 2)}

What it means

After the audit response parses as JSON, `audit.js:261` requires a `metadata` field (`if (!responseJson.metadata)`). Its absence means the endpoint returned syntactically valid JSON but the wrong shape — typically a generic registry error object, a health-check payload, or an API-version mismatch.

Source

Thrown at src/cli/commands/audit.js:261

    const requestBody = await gzip(JSON.stringify(auditTree));
    const response = await this.config.requestManager.request({
      url: `${registry}/-/npm/v1/security/audits`,
      method: 'POST',
      body: requestBody,
      headers: {
        'Content-Encoding': 'gzip',
        'Content-Type': 'application/json',
        Accept: 'application/json',
      },
    });

    try {
      responseJson = JSON.parse(response);
    } catch (ex) {
      throw new Error(`Unexpected audit response (Invalid JSON): ${response}`);
    }
    if (!responseJson.metadata) {
      throw new Error(`Unexpected audit response (Missing Metadata): ${JSON.stringify(responseJson, null, 2)}`);
    }
    this.reporter.verbose(`Audit Response: ${JSON.stringify(responseJson, null, 2)}`);
    return responseJson;
  }

  _insertWorkspacePackagesIntoManifest(manifest: Object, resolver: PackageResolver) {
    if (resolver.workspaceLayout) {
      const workspaceAggregatorName = resolver.workspaceLayout.virtualManifestName;
      const workspaceManifest = resolver.workspaceLayout.workspaces[workspaceAggregatorName].manifest;

      manifest.dependencies = Object.assign(manifest.dependencies || {}, workspaceManifest.dependencies);
      manifest.devDependencies = Object.assign(manifest.devDependencies || {}, workspaceManifest.devDependencies);
      manifest.optionalDependencies = Object.assign(
        manifest.optionalDependencies || {},
        workspaceManifest.optionalDependencies,
      );
    }
  }

View on GitHub (pinned to c2dda503f3)

Solutions

  1. Use the official registry for audit (`yarn audit --registry https://registry.yarnpkg.com`).
  2. Upgrade or reconfigure the private registry/mirror to support the audit endpoint.
  3. Inspect `responseJson` (logged via `reporter.verbose`) to identify the unexpected shape.
  4. Retry to rule out a transient wrong-shape response.

Example fix

// before: mirror returns { "error": "audit not supported" }
$ yarn audit

// after
$ yarn audit --registry https://registry.yarnpkg.com
Defensive patterns

Strategy: type-guard

Validate before calling

function validateAuditShape(json: unknown): asserts json is { metadata: object } {
  if (!json || typeof json !== 'object' || !('metadata' in json)) {
    throw new Error('Audit response missing metadata; registry may not support audit');
  }
}
// const data = await response.json(); validateAuditShape(data);

Type guard

function hasAuditMetadata(res: unknown): res is { metadata: object } {
  return typeof res === 'object' && res !== null && 'metadata' in res;
}

Try / catch

try {
  await runAudit();
} catch (e) {
  if (/Missing Metadata/.test(e.message)) {
    // fall back to official registry or skip audit in CI
  } else throw e;
}

Prevention

When it happens

Trigger: `responseJson.metadata` is falsy after a successful `JSON.parse`. Happens when the audit endpoint answers with an error envelope (`{"error": "..."}`), a legacy/unsupported audit API version, or a mirror that returns `{}` for unsupported routes.

Common situations: Verdaccio/Artifactory/Nexus mirror with audit disabled or an older npm-audit protocol, registry returning `{"ok": true}` health responses on the audit route, or a CDN returning a cached JSON error.

Related errors


AI-assisted analysis of yarnpkg/yarn@c2dda503f3 (2026-08-13). Data as JSON: /api/errors/bb58fa4c7291b89f. Report an issue: GitHub.