{"record":{"id":"35bc36a9d9747980","repo":"yarnpkg/yarn","slug":"unexpected-audit-response-invalid-json-respon","errorCode":null,"errorMessage":"Unexpected audit response (Invalid JSON): ${response}","messagePattern":"Unexpected audit response \\(Invalid JSON\\): (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/cli/commands/audit.js","lineNumber":258,"sourceCode":"    let responseJson;\n    const registry = YARN_REGISTRY;\n    this.reporter.verbose(`Audit Request: ${JSON.stringify(auditTree, null, 2)}`);\n    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,","sourceCodeStart":240,"sourceCodeEnd":276,"githubUrl":"https://github.com/yarnpkg/yarn/blob/c2dda503f3759b5be5f0e24ecd9cf5c97a540147/src/cli/commands/audit.js#L240-L276","documentation":"The audit command POSTs the dependency bundle (gzipped JSON) to the registry audit endpoint, then `JSON.parse(response)` is wrapped in try/catch at `audit.js:258`. If the body is not valid JSON the catch rethrows this error with the raw response inlined. It indicates the endpoint returned HTML, plain text, an error page, or an empty body rather than the expected JSON document.","triggerScenarios":"`JSON.parse(response)` throws inside the audit handler — the registry/audit endpoint returned a non-JSON body. Common with corporate proxies, captive portals, misconfigured `registry` in `.yarnrc`, or registry outages.","commonSituations":"Custom/private registry that does not implement the npm audit HTTP API, a transparent proxy injecting an HTML login page, an air-gapped network, or `https-proxy-agent` returning a proxy error page.","solutions":["Check `yarn config get registry` and point it at a registry that supports audit (official `https://registry.yarnpkg.com`).","Retry; transient outages or proxy hiccups often resolve.","If behind a proxy, verify `HTTP_PROXY`/`HTTPS_PROXY` and that it permits the audit POST.","Run `curl -v <registry>/-/npm/v1/security/audit` to inspect the raw body returned."],"exampleFix":"// before\n$ yarn audit   // registry returns HTML login page\n\n// after\n$ yarn config set registry https://registry.yarnpkg.com\n$ yarn audit","handlingStrategy":"retry","validationCode":"// Probe the audit endpoint shape before delegating to yarn audit\nasync function auditEndpointOk(registry: string): Promise<boolean> {\n  try {\n    const res = await fetch(`${registry}/-/npm/v1/security/audit`, { method: 'POST', body: '{}' });\n    const txt = await res.text();\n    try { JSON.parse(txt); return true; } catch { return false; }\n  } catch { return false; }\n}","typeGuard":"function looksLikeJson(s: string): boolean {\n  const t = s.trim();\n  return (t.startsWith('{') || t.startsWith('[')) && t.length > 0;\n}","tryCatchPattern":"async function auditWithRetry(runAudit, attempts = 3) {\n  for (let i = 0; i < attempts; i++) {\n    try { return await runAudit(); }\n    catch (e) {\n      if (/Invalid JSON/.test(e.message) && i < attempts - 1) {\n        await new Promise(r => setTimeout(r, 500 * (i + 1)));\n        continue;\n      }\n      throw e;\n    }\n  }\n}","preventionTips":["Pin `registry` to a known-good value in CI rather than relying on ambient config.","Verify proxy egress for the audit POST endpoint.","Treat 'Invalid JSON' as transient first — retry before escalating."],"tags":["audit","network","registry","json","proxy"],"backgroundTag":null,"analyzedSha":"c2dda503f3759b5be5f0e24ecd9cf5c97a540147","analyzedAt":"2026-08-13T04:17:06.305Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}