Skip to content

fix(npm): bypass @npmcli/agent to fix proxy env var crash#21832

Open
GoldJohnKing wants to merge 4 commits intoanomalyco:devfrom
GoldJohnKing:fix/proxy-agent-url-object
Open

fix(npm): bypass @npmcli/agent to fix proxy env var crash#21832
GoldJohnKing wants to merge 4 commits intoanomalyco:devfrom
GoldJohnKing:fix/proxy-agent-url-object

Conversation

@GoldJohnKing
Copy link
Copy Markdown

@GoldJohnKing GoldJohnKing commented Apr 10, 2026

Issue for this PR

Closes #21098
Closes #21327
Closes #21468
Closes #21472

Type of change

  • Bug fix
  • New feature
  • Refactor / code improvement
  • Documentation

What does this PR do?

When HTTP_PROXY / HTTPS_PROXY env vars are set, plugin installation via npm crashes with fetch() proxy.url must be a non-empty string.

The cause is a type mismatch between @npmcli/agent and Bun's node:http polyfill. Arborist's dependency chain uses @npmcli/agent which reads proxy env vars and exposes .proxy as { url: URL_object } (a JS URL instance, not a string). Bun's node:http polyfill (_http_client.ts) reads agent.proxy and passes it to native fetch(). Bun's native fetch validates that proxy.url is a string, but a URL object fails this check.

The fix: pass agent: false to Arborist on Bun runtime. This skips @npmcli/agent entirely. Bun's FetchTasklet then handles proxy itself by reading HTTP_PROXY/HTTPS_PROXY from process.env as plain strings, which works correctly. The option is only applied when typeof Bun !== "undefined", so Node.js is unaffected.

How did you verify your code works?

  • tsc --noEmit — no new errors in src/npm/index.ts
  • Built a Linux x64 binary with bun run script/build.ts --single --skip-embed-web-ui --skip-install — smoke test (--version) passed
  • Reviewed Bun source (fetch.zig, FetchTasklet.zig, _http_client.ts) and @npmcli/agent source to confirm the fix routes proxy through Bun's working env var fallback path
  • Manually test to confirm problem fixed.

Screenshots / recordings

N/A — no UI change.

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR

When HTTP_PROXY/HTTPS_PROXY env vars are set, @npmcli/arborist's
dependency chain (@npmcli/agent) creates a proxy agent whose .proxy
getter returns { url: URL_object }. Bun's node:http polyfill reads
this and passes it to native fetch(), which expects proxy.url to be a
string, not a URL instance. This triggers:
  fetch() proxy.url must be a non-empty string

Pass agent:false to Arborist to skip @npmcli/agent entirely. Bun's
native fetch layer then handles proxy via its own env var fallback
(HTTP_PROXY/HTTPS_PROXY), which works correctly with string URLs.

Fixes anomalyco#21098
Fixes anomalyco#21327
Fixes anomalyco#21468
Fixes anomalyco#21472
@github-actions github-actions bot added needs:compliance This means the issue will auto-close after 2 hours. and removed needs:compliance This means the issue will auto-close after 2 hours. labels Apr 10, 2026
@github-actions
Copy link
Copy Markdown
Contributor

Thanks for updating your PR! It now meets our contributing guidelines. 👍

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

Labels

None yet

Projects

None yet

2 participants