{"record":{"id":"bb58fa4c7291b89f","repo":"yarnpkg/yarn","slug":"unexpected-audit-response-missing-metadata-js","errorCode":null,"errorMessage":"Unexpected audit response (Missing Metadata): ${JSON.stringify(responseJson, null, 2)}","messagePattern":"Unexpected audit response \\(Missing Metadata\\): (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/cli/commands/audit.js","lineNumber":261,"sourceCode":"    const requestBody = await gzip(JSON.stringify(auditTree));\n    const response = await this.config.requestManager.request({\n      url: `${registry}/-/npm/v1/security/audits`,\n      method: 'POST',\n      body: requestBody,\n      headers: {\n        'Content-Encoding': 'gzip',\n        'Content-Type': 'application/json',\n        Accept: 'application/json',\n      },\n    });\n\n    try {\n      responseJson = JSON.parse(response);\n    } catch (ex) {\n      throw new Error(`Unexpected audit response (Invalid JSON): ${response}`);\n    }\n    if (!responseJson.metadata) {\n      throw new Error(`Unexpected audit response (Missing Metadata): ${JSON.stringify(responseJson, null, 2)}`);\n    }\n    this.reporter.verbose(`Audit Response: ${JSON.stringify(responseJson, null, 2)}`);\n    return responseJson;\n  }\n\n  _insertWorkspacePackagesIntoManifest(manifest: Object, resolver: PackageResolver) {\n    if (resolver.workspaceLayout) {\n      const workspaceAggregatorName = resolver.workspaceLayout.virtualManifestName;\n      const workspaceManifest = resolver.workspaceLayout.workspaces[workspaceAggregatorName].manifest;\n\n      manifest.dependencies = Object.assign(manifest.dependencies || {}, workspaceManifest.dependencies);\n      manifest.devDependencies = Object.assign(manifest.devDependencies || {}, workspaceManifest.devDependencies);\n      manifest.optionalDependencies = Object.assign(\n        manifest.optionalDependencies || {},\n        workspaceManifest.optionalDependencies,\n      );\n    }\n  }","sourceCodeStart":243,"sourceCodeEnd":279,"githubUrl":"https://github.com/yarnpkg/yarn/blob/c2dda503f3759b5be5f0e24ecd9cf5c97a540147/src/cli/commands/audit.js#L243-L279","documentation":"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.","triggerScenarios":"`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.","commonSituations":"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.","solutions":["Use the official registry for audit (`yarn audit --registry https://registry.yarnpkg.com`).","Upgrade or reconfigure the private registry/mirror to support the audit endpoint.","Inspect `responseJson` (logged via `reporter.verbose`) to identify the unexpected shape.","Retry to rule out a transient wrong-shape response."],"exampleFix":"// before: mirror returns { \"error\": \"audit not supported\" }\n$ yarn audit\n\n// after\n$ yarn audit --registry https://registry.yarnpkg.com","handlingStrategy":"type-guard","validationCode":"function validateAuditShape(json: unknown): asserts json is { metadata: object } {\n  if (!json || typeof json !== 'object' || !('metadata' in json)) {\n    throw new Error('Audit response missing metadata; registry may not support audit');\n  }\n}\n// const data = await response.json(); validateAuditShape(data);","typeGuard":"function hasAuditMetadata(res: unknown): res is { metadata: object } {\n  return typeof res === 'object' && res !== null && 'metadata' in res;\n}","tryCatchPattern":"try {\n  await runAudit();\n} catch (e) {\n  if (/Missing Metadata/.test(e.message)) {\n    // fall back to official registry or skip audit in CI\n  } else throw e;\n}","preventionTips":["Confirm the private registry/mirror implements the audit API before relying on it.","Run audit against the official registry explicitly with `--registry`.","Log `reporter.verbose` output to capture the unexpected response shape."],"tags":["audit","registry","json","api-mismatch"],"backgroundTag":null,"analyzedSha":"c2dda503f3759b5be5f0e24ecd9cf5c97a540147","analyzedAt":"2026-08-13T04:17:06.305Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}