nodejs/node · error · Error
Could not read package.json from tarball
Error message
Could not read package.json from tarball
What it means
Thrown by the staging download path when the fetched tarball's entries never yielded a `package/package.json` entry, leaving `manifestJson` null after `stream.end()`. Every npm tarball must contain `package/package.json` at its root; absence means the tarball is malformed or the registry returned unexpected content.
Source
Thrown at deps/npm/lib/commands/stage/download.js:64
async #readManifestFromTarball (tarballData) {
let manifestJson
const stream = tar.t({
onentry (entry) {
if (entry.path === 'package/package.json') {
const chunks = []
entry.on('data', c => chunks.push(c))
entry.on('end', () => {
manifestJson = JSON.parse(Buffer.concat(chunks).toString())
})
} else {
entry.resume()
}
},
})
// node-tar uses Minipass which processes synchronously on .end()
stream.end(tarballData)
if (!manifestJson) {
throw new Error('Could not read package.json from tarball')
}
return manifestJson
}
}
module.exports = StageDownload
View on GitHub (pinned to 1b2de5e052)
Solutions
- Verify the staged tarball URL/ID is correct and the registry actually serves a valid package tarball.
- Download the artifact manually and inspect it: `tar -tzf file.tgz | head` should list `package/package.json`.
- Check registry/proxy responses (auth, redirect, error body) that may substitute non-tarball content.
- Re-stage or re-publish the package so the tarball is well-formed.
Example fix
// before: tarball missing package/package.json // after: ensure tarball layout is package/<files> tar -tzf pkg.tgz // must show package/package.json
Defensive patterns
Strategy: validation
Validate before calling
const tar = require('tar')
async function assertTarballHasManifest(buffer) {
let found = false
await tar.t({ file: /* path or */ null, onentry(e){ if (e.path === 'package/package.json') found = true } })
// for a Buffer use: const s = tar.t({onentry...}); s.end(buffer); await once(s,'end')
if (!found) throw new Error('Tarball has no package/package.json entry')
return true
} Try / catch
try {
await stageDownload(stageId)
} catch (e) {
if (/Could not read package\.json from tarball/i.test(e.message)) {
// re-fetch / verify registry response body, then retry once
}
throw e
} Prevention
- Validate tarballs with `tar -tzf file.tgz | grep package/package.json` before staging.
- Log the registry response content-type/size to catch HTML error pages masquerading as tarballs.
- Pin and verify registry/proxy configuration for staging workflows.
When it happens
Trigger: `#readManifestFromTarball` iterates the tar entries and finds none whose `entry.path === 'package/package.json'`; after synchronous `stream.end(tarballData)`, `manifestJson` is still undefined.
Common situations: Registry or proxy returned an HTML error page saved as a `.tgz`; a manually crafted tarball with a different top-level directory; a corrupted/partial download; a private registry misconfiguration returning JSON instead of a tarball.
Related errors
- You cannot publish over the previously published versions: $
- Missing script: "${event}"${suggestions} To see a list of s
- invalid version range: ${spec}
- ${tag} is not a dist-tag on ${spec.name}
- No dist-tags found for ${spec.name}
AI-assisted analysis of nodejs/node@1b2de5e052 (2026-08-13).
Data as JSON: /api/errors/281dc1fbbff5dfce.
Report an issue: GitHub.