fix: sync json output of pack and publish - #9247
Merged
Merged
Conversation
BREAKING CHANGE: the --json output of `npm pack` and `npm publish` have changed. They are now always consistent, and in the same format. Previously, `npm pack` would output an array of entries and `npm publish` an object. The `npm publish` object also changed forms depending on if workspaces were also being published. Now, the output is always an object with the package name as the top level index.
owlstronaut
approved these changes
Apr 16, 2026
reggi
pushed a commit
that referenced
this pull request
Apr 21, 2026
BREAKING CHANGE: the --json output of `npm pack` and `npm publish` have changed. They are now always consistent, and in the same format. Previously, `npm pack` would output an array of entries and `npm publish` an object. The `npm publish` object also changed forms depending on if workspaces were being published. Now, the output is always an object with the package name as the top level index. fixes npm/statusboard#1073
This was referenced May 20, 2026
reggi
added a commit
that referenced
this pull request
May 20, 2026
`npm stage download <id> --json` currently emits the package contents
under a literal `"undefined"` key because `logTar` is called without a
`key` option.
### Before
```json
{
"undefined": {
"name": "polo-meow-meow-meow",
"version": "1.0.3",
...
}
}
```
### After
```json
{
"polo-meow-meow-meow": {
"name": "polo-meow-meow-meow",
"version": "1.0.3",
...
}
}
```
This matches the JSON shape of `npm publish --json` and `npm pack
--json`.
### Background
The `key == null` fallback in `lib/utils/tar.js` (that would have
rendered a bare object when no key was passed) was removed from `latest`
in #9247 ("fix: sync json output of pack and publish") as a `BREAKING
CHANGE`. Per that PR:
> BREAKING CHANGE: the --json output of `npm pack` and `npm publish`
have changed. They are now always consistent, and in the same format.
>
> Previously, `npm pack` would output an array of entries and `npm
publish` an object. The `npm publish` object also changed forms
depending on if workspaces were being published.
>
> Now, the output is always an object with the package name as the top
level index.
When #9201 (npm stage) landed, it added a new `logTar` caller in
`lib/commands/stage/download.js` that did not pass a `key`, silently
violating the v12 contract established in #9247 and producing the
`"undefined"` wrapper. This PR brings the new caller into compliance.
### Repro
```
npm stage download <stage-id> --json
```
A follow-up backports this to `release/v11` for consistent output across
branches: #9381.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
reggi
added a commit
that referenced
this pull request
May 20, 2026
Backports #9380 to `release/v11` to keep `npm stage download --json` output consistent across branches. On `release/v11`, the `key == null` guard in `lib/utils/tar.js` was emitting the bare object (no wrapper key). This change adds a key so the output matches `latest` and aligns with `npm publish --json` / `npm pack --json`. ### Before (on release/v11) ```json { "name": "polo-meow-meow-meow", "version": "1.0.3", ... } ``` ### After ```json { "polo-meow-meow-meow": { "name": "polo-meow-meow-meow", "version": "1.0.3", ... } } ``` ### Background The `key == null` fallback in `lib/utils/tar.js` (still present on `release/v11`) was removed from `latest` in #9247 ("fix: sync json output of pack and publish") as a `BREAKING CHANGE`. Per that PR: > BREAKING CHANGE: the --json output of `npm pack` and `npm publish` have changed. They are now always consistent, and in the same format. > > Previously, `npm pack` would output an array of entries and `npm publish` an object. The `npm publish` object also changed forms depending on if workspaces were being published. > > Now, the output is always an object with the package name as the top level index. That breaking change was intentionally not backported to v11 (maintenance branch), so the fallback still exists here. This backport keeps the call-site contract aligned across branches so consumers get the same `{ "<pkg>": {...} }` shape on both. Clean cherry-pick of 9f7834d from #9380. --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
reggi
added a commit
that referenced
this pull request
Jul 10, 2026
npm pack --json now emits an object keyed by package name (#9247) instead of an array, so the release integration workflow's jq -r .[0].filename fails with 'Cannot index object with number'. Parse the filename from the object instead. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 91528ac3-495a-4617-9630-c31478a0691f
reggi
added a commit
that referenced
this pull request
Jul 10, 2026
## Problem The `build nodejs` jobs in `Release Integration / publish` fail at `.github/workflows/node-integration.yml`: ``` node . pack --loglevel=silent --json | jq -r .[0].filename → jq: error (at <stdin>:9859): Cannot index object with number → Process completed with exit code 5 ``` As of #9247 (sync json output of pack and publish), `npm pack --json` no longer outputs an array. `logTar` now buffers `{ [tar.name]: tarball }`, so the output is an object keyed by package name: ```json { "npm": { "filename": "npm-12.0.1.tgz", ... } } ``` The workflow still parsed it with `.[0].filename`, which errors on an object. npm 12.0.x is the first release carrying this change, so the release integration only started breaking now. ## Fix Parse the filename from the object instead of an array index: ```diff -npmtarball="$(node . pack --loglevel=silent --json | jq -r .[0].filename)" +npmtarball="$(node . pack --loglevel=silent --json | jq -r 'to_entries[0].value.filename')" ``` Verified locally: returns `npm-12.0.1.tgz`. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
3 tasks
mbanderas
added a commit
to mbanderas/maestro-agora
that referenced
this pull request
Aug 9, 2026
npm 11 and earlier describe a pack as an array of packages. npm 12 returns an object keyed by package name instead (npm/cli#9247), so payload.length was undefined and the assertion read "undefined !== 1". The check now normalizes both shapes and asserts that a file list actually came back. The publish workflow no longer installs npm@latest before publishing. That step is what pulled npm 12 into a release path tested only against npm 11, and the npm bundled with Node 24 already meets the 11.5.1 floor that trusted publishing requires. It records the toolchain versions instead. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Pm3XF1hsWYYLccRnVtPWhs
acburdine
added a commit
to TryGhost/Ghost-CLI
that referenced
this pull request
Aug 18, 2026
fixes #2309 - npm 12 (npm/cli#9247) changed `npm pack --json` from a JSON array of packed tarballs to an object keyed by package name. Users with npm >=12 installed globally hit "'npm pack' did not return a tarball" (or, before 1.32.1, a cryptic "object is not iterable") when updating Ghost, since the CLI only handled the array shape. - normalize both formats before reading the tarball filename.
acburdine
added a commit
to TryGhost/Ghost-CLI
that referenced
this pull request
Aug 18, 2026
fixes #2309 - npm 12 (npm/cli#9247) changed `npm pack --json` from a JSON array of packed tarballs to an object keyed by package name. Users with npm >=12 installed globally hit "'npm pack' did not return a tarball" (or, before 1.32.1, a cryptic "object is not iterable") when updating Ghost, since the CLI only handled the array shape. - normalize both formats before reading the tarball filename.
|
This change makes it impossible to run |
This was referenced Aug 24, 2026
8 tasks
mortenbrudvik
added a commit
to mortenbrudvik/waveui
that referenced
this pull request
Sep 26, 2026
npm 12 prints `npm pack --json` as an object keyed by package name instead of an array of results (npm/cli#9247, listed as a breaking change in the npm 12.0.0 release notes). pack() parsed from the first `[`, which with npm 12 opens the `files` array, so JSON.parse threw "Unexpected non-whitespace character after JSON". With npm 12.1.0 this failed `npm run test:pack`, `npm run check:package` (attw-pack.mjs packs through pack()) and two Vitest tests: pack-smoke.test.mjs "pack > writes the tarball under npm publish --dry-run" and attw-pack.test.mjs. - scripts/pack-smoke.mjs: new exported parsePackOutput(stdout). It starts at the first line that opens with `[` or `{` (skipping anything printed before the JSON), accepts the array (npm 10, 11) and the object (npm 12) shape, and throws a readable error for output without JSON or with other than one package. pack() uses it. - scripts/__tests__/pack-smoke.test.mjs: parsePackOutput tests for both shapes, for lines before the JSON and for the error cases.
hussamsoft
added a commit
to hussamsoft/OhMyPCode
that referenced
this pull request
Sep 26, 2026
…alse-positive provider substring check Three unrelated, pre-existing failures surfaced during post-provider-fix server-suite triage (786s full run, 6 failed files / 7 failed tests down from the earlier much larger baseline). None are provider-enablement related; fixed here since they're genuine bugs, not flaky/environmental: - scripts/test-support/npm-registry.mts: npm >= 12 changed 'npm pack --json' from an array of packed-package objects to a single object keyed by package name (npm/cli#9247, confirmed via community sources + reproduced locally against the installed npm 12.1.0: 'npm pack --json' on a trivial fixture package returns {"pkg-name": {...}}, not [{...}]). The shared test fixture harness (used by packages/server's plugins/index.posix.test.ts and packages/cli's e2e plugin-lifecycle test) indexed packed[0] unconditionally and crashed with 'Cannot read properties of undefined'. Normalized both shapes with Array.isArray/Object.values rather than pinning to one npm major. - packages/server/src/server/plugins/managed-source/npm.ts: fixed a second, real production bug the above fix exposed (the posix plugin test was crashing before reaching this code path). Applying a previously reviewed plugin update writes package.json's dependency as an exact tarball URL (dependencies: { [packageName]: target.resolved }) so the installed artifact can be verified byte-for-byte against what was reviewed. npm >= 12 defaults allow-remote=none, its new install-time supply-chain hardening, which blocks exactly this shape (a root dependency pinned to a raw tarball URL) unless the URL shares a hostname with the configured registry -- a hostname-matching heuristic that doesn't reliably cover every registry/ mirror setup. Added --allow-remote=root: permits fetching our own, already-integrity-verified root dependency, but not transitive ones, matching the minimum privilege this call actually needs. - terminal/agent-hooks/claude/claude.test.ts: 'keeps provider names out of the generic server bootstrap' asserted source.toLowerCase().not.toContain (providerId) for every AGENT_HOOK_PROVIDERS key. Once 'omp' became a real provider id, this became a structural false positive -- 'omp' is a common substring of ordinary English words (component, complete, accomplish...) that necessarily appear in a large source file, unrelated to any actual provider-specific logic leaking into the generic bootstrap. Switched to a word-boundary regex (\bomp\b) so the check still catches what it's meant to (a real reference to the provider id as an identifier or string) without false-positiving on prose-like substrings. Verified: index.posix.test.ts 23/23 (was crashing before even reaching the assertion), claude.test.ts 7/7 (5 skipped, expected). Repo-wide typecheck 0, lint 0. Remaining 4 of the original 7 server failures (checkout-git.test.ts x2, paseo-worktree-service.test.ts, checkout-session.test.ts) all trace to the same still-unresolved external blocker: the stray, empty .git in the user's home directory (C:\Users\hussa\.git), pending explicit approval to delete. opencode-server-manager.test.ts's Windows-only npm-shim-resolution test is a local-machine environment gap, not a code bug: this machine's globally installed 'opencode' shim resolves to node_modules/@opencode/cli/bin/opencode.exe, not the node_modules/opencode-ai/bin/opencode.exe the test (and the real resolution logic) expect -- the test's own assertion message says as much ('Windows CI must install opencode-ai before server tests').
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
BREAKING CHANGE: the --json output of
npm packandnpm publishhave changed. They are now always consistent, and in the same format.Previously,
npm packwould output an array of entries andnpm publishan object. Thenpm publishobject also changed forms depending on if workspaces were being published.Now, the output is always an object with the package name as the top level index.
fixes npm/statusboard#1073