Skip to content

"shopify hydrogen dev" aborts on startup in a network-restricted environment (@shopify/cli 4.7.1 cancellation race) #174

Description

@paul-phan

DRAFT — not posted. For Paul's approval before anything goes to Weaverse/pilot.

Repo: Weaverse/pilot
Title: shopify hydrogen dev aborts on startup in a network-restricted environment (@shopify/cli 4.7.1 cancellation race)

Summary

On Pilot 4a99511d (v2026.9.7), npm run dev exits 1 during startup whenever the environment cannot
reach the npm registry. The failure comes from @shopify/cli's startup version-check path, not from
Pilot code or from Vite/Hydrogen:

> @weaverse/pilot@2026.9.7 dev
> react-router typegen && shopify hydrogen dev --codegen --port "$PORT"
…
[vite] (client) Re-optimizing dependencies because vite config has changed
[vite] (ssr) Re-optimizing dependencies because vite config has changed
Error: The `onCancel` handler was attached after the promise settled.
    at o (node_modules/@shopify/cli/dist/latest-version-LDWU5F7A.js:11:17603)
    at d (node_modules/@shopify/cli/dist/latest-version-LDWU5F7A.js:19:47843)
    at t.<anonymous> (node_modules/@shopify/cli/dist/latest-version-LDWU5F7A.js:19:49069)
    at t.wrapper (node:events:639:12)
    at t.emit (node:events:514:20)
    at t.emit (node:domain:473:12)
    at node_modules/@shopify/cli/dist/latest-version-LDWU5F7A.js:19:37968
    at runNextTicks (node:internal/process/task_queues:65:5)
    at processTimers (node:internal/timers:615:9)

The message is p-cancelable's guard: an onCancel handler is attached to a promise that has
already settled. The frame chain ends in processTimers, so the throw is raised from a timer inside
the version-check/self-upgrade flow, escapes through node:domain, and terminates the CLI process
before the dev server ever listens. The dev server never prints ➜ Local:; the surrounding Miniflare
instance then reports ERR_DISPOSED as a consequence of the teardown.

Environment

  • Pilot 4a99511d (v2026.9.7), unmodified lockfile (@shopify/cli 4.7.1; registry latest 4.8.0)
  • Node 26.8.2, npm 11.19.1, Debian trixie (node:26-slim), linux/arm64
  • Dev command exactly as Pilot defines it, only --port taken from the environment
  • No egress to the npm registry; name resolution and outbound TCP are denied by the host

Reproduction

  1. npm ci on a machine with network, so node_modules is complete.
  2. Remove registry reachability (any of: firewall DROP, firewall REJECT, or no route at all).
  3. PORT=3458 npm run dev.

Observed: exits 1 with the trace above. The CLI announces
✨ New version of Shopify CLI available! (4.7.1 → 4.8.0) Now upgrading by running: npm install -g @shopify/cli@latest
when it can read the registry, so the crash sits on the path that learns about / installs a newer CLI.

Notably not the cause

  • Denial latency. Measured in the failing environment: a denied TCP connect now returns
    ECONNREFUSED in 3 ms (nftables reject with tcp reset), and the crash still occurs.
    Black-holing (drop) crashes identically.
  • CI=1. Set for the process; no effect.
  • SHOPIFY_CLI_ENV=development. No effect on the crash in our matrix.
  • There is no documented SHOPIFY_CLI_* switch that disables the version check; the only guard in
    the bundle is isPreReleaseVersion(version).

Impact

Any deployment that runs Pilot's dev server without npm-registry access — CI sandboxes, offline
development, restricted-egress hosting — cannot start the storefront at all. It is a hard startup
failure, not a degraded notification.

Suggested fix

Guard the version-check/self-upgrade flow so a failure (or a promise that settles before the
cancellation handler is attached) can never reject into the process: await it with a catch, or
skip it when the registry is unreachable. Pinning @shopify/cli past the race in Pilot's lockfile
would unblock consumers in the meantime.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    • Status
      Todo

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions