Skip to content

Fix dev container build failure caused by npm registry dependency - #102

Closed
ayeshurun wants to merge 1 commit into
mainfrom
dev/alonyeshurun/jubilant-fiesta
Closed

Fix dev container build failure caused by npm registry dependency#102
ayeshurun wants to merge 1 commit into
mainfrom
dev/alonyeshurun/jubilant-fiesta

Conversation

@ayeshurun

Copy link
Copy Markdown
Owner

Problem

The dev container fails to build during the Node.js feature install:

npm error code ECONNRESET
npm error network request to https://registry.npmjs.org/pnpm failed, reason:
  Client network socket disconnected before secure TLS connection was established
ERROR: Feature "Node.js (via nvm), yarn and pnpm." (ghcr.io/devcontainers/features/node) failed to install!

Root cause

registry.npmjs.org is unreachable, while every other endpoint in the same build succeeded (nodejs.org, ghcr.io, mcr.microsoft.com). Reproduced outside the container:

$ curl -m 25 https://registry.npmjs.org/changie   ->  curl: (35) Recv failure: Socket is not connected
$ curl -m 25 https://api.github.com/...            ->  200

This is a network-level block on npm (typical of corporate TLS-inspection proxies), not a transient outage — retrying does not help.

Two independent steps depended on that registry:

  1. The node feature installs pnpm by default (npm install -g pnpm). This is the step that fails the image build. pnpm is not used anywhere in this repository.
  2. postCreateCommand runs npm install -g changie. This would fail the same way even after the image built, so fixing only (1) would have moved the failure rather than resolved it.

Changes

.devcontainer/devcontainer.json — set "pnpmVersion": "none" on the node feature. Confirmed against the feature's install.sh that none is explicitly handled (Ignoring installation of PNPM), so this is a real no-op rather than a silently ignored option. With pnpm skipped, the feature makes no npm registry calls at all (node comes from nodejs.org, yarn is already in the base image, npmVersion already defaults to none).

scripts/install_dev_container_dependencies.sh — replace npm install -g changie with a direct GitHub release download:

  • architecture-aware (amd64 / arm64)
  • SHA256-verified against the release's published checksums.txt, using an exact filename match so a substring collision cannot select the wrong digest
  • pinned version, curl --retry, and fails loudly rather than silently continuing
  • sudo is now applied conditionally, because installing into /usr/local/bin requires elevation if lifecycle scripts run as the vscode remote user rather than root

Net effect: the dev container setup no longer touches the npm registry at any point.

Validation

Run against the actual base image mcr.microsoft.com/devcontainers/python:1-3.12-bullseye:

Case Result
linux/arm64, vscode user checksum OK, changie version v1.26.0
linux/arm64, root checksum OK, changie version v1.26.0
linux/amd64, vscode user checksum OK, changie version v1.26.0
Bad version (404) exits non-zero, no silent success
changie latest / changie next patch against this repo's .changie.yaml v1.7.0 / v1.7.1

Also confirmed the base image ships nvm and yarn but no node binary, so the feature is genuinely performing the install (the image's devcontainer.metadata label claiming a node feature is misleading).

Trade-offs and open points

Flagging these explicitly rather than burying them:

  • changie is now pinned to 1.26.0, where npm i -g changie previously resolved to latest. This gains reproducibility but will go stale and needs deliberate bumping.
  • I could not verify that the npm changie package and miniscruff/changie GitHub releases share a version stream, because npm is unreachable from this machine. The installed binary works correctly against this repo's config, but the resolved version may differ from what contributors got previously.
  • The Node.js feature is now unused by this repository. Nothing here needs node — it was only present to install changie. I deliberately kept it to avoid removing a capability contributors may rely on, but removing it would cut build time and one more external dependency. Happy to drop it if preferred.
  • No changie entry included. This is a developer-tooling fix with no user-facing CLI impact, so a release-note entry would be noise. This likely wants the skip-changelog label; the 🔄 Changelog check will otherwise fail.
  • This does not fix the underlying network block. It removes the dev container's dependency on the blocked endpoint. Anyone whose network also blocks github.com release assets will still fail — though that was verified reachable here.

The dev container build fails during the Node.js feature install when
registry.npmjs.org is unreachable (npm ECONNRESET / "Client network socket
disconnected before secure TLS connection was established"), which is common
behind corporate proxies. Two separate steps depended on that registry:

1. The node feature installs pnpm by default via `npm install -g pnpm`.
   pnpm is not used by this repository, so it is now disabled with
   `pnpmVersion: none`.

2. `postCreateCommand` ran `npm install -g changie`, which would fail the
   same way even after the image built. changie ships as a single Go binary,
   so it is now downloaded directly from its GitHub release and verified
   against the published SHA256 checksum.

Together these remove all npm registry access from the dev container setup.

Also make `sudo` usage conditional in the setup script so it works whether
lifecycle scripts run as root or as the `vscode` remote user, since
installing into /usr/local/bin requires elevated permissions in the latter
case.

Verified in mcr.microsoft.com/devcontainers/python:1-3.12-bullseye on both
linux/arm64 and linux/amd64, as root and as `vscode`, including checksum
verification, loud failure on a bad download, and `changie` correctly
parsing this repository's .changie.yaml.

Co-authored-by: Copilot App <[email protected]>
@ayeshurun

Copy link
Copy Markdown
Owner Author

Closing in favour of #97. Three PRs (#97, #101, #102) were opened for this same bug; consolidating on #97.

The diagnosis here is sound and pnpmVersion: "none" is a legitimate way to stop the feature calling the npm registry — verified against the feature's install.sh, as the description says. But this PR fixes only the first of three failures on the affected setup. Building the branch reaches postCreateCommand and then hits:

1. apt-get update exits 100. The base image mcr.microsoft.com/devcontainers/python:1-3.12-bullseye ships a stale /etc/apt/sources.list.d/yarn.list:

The following signatures could not be verified because the public key is not
available: NO_PUBKEY 62D54FD4003F6525
E: The repository "https://dl.yarnpkg.com/debian stable InRelease" is not signed.

This branch keeps $SUDO apt-get update && $SUDO apt-get install -y ..., so under set -e the compound command returns non-zero and the script aborts. #97 removes the stale list file first.

2. pip3 install -r requirements-dev.txt fails. On the reporting network files.pythonhosted.org is blocked (curl → 000) even though pypi.org/simple/ returns 200 — the index is reachable while the artifact CDN is not, which makes this easy to misdiagnose. There is no mechanism here to point pip at an internal mirror. #97 adds a git-ignored .devcontainer/local.env.

Also worth noting: keeping the node feature retains a Node toolchain that nothing in this repository uses — there is no package.json and no JavaScript. #97 drops the feature entirely, which removes the failure class rather than configuring around it.

The changie install here is close to #97's (pinned version, checksums.txt with exact filename match, conditional sudo, loud failure). #97 additionally preserves proxy variables through sudo, checks that sudo exists and is passwordless, traps cleanup on EXIT, sets --proto =https and connect/max timeouts, and extracts the binary to stdout so a substituted archive cannot use a symlink to redirect the privileged install.

I rebuilt #97 end-to-end on the affected network with no PIP_* variables set: {"outcome":"success"}, changie version v1.26.0, node absent, apt-get update clean.

One gap this PR has independently of the above: no .changes/unreleased/ entry, which CONTRIBUTING.md requires.

@ayeshurun ayeshurun closed this Aug 30, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant