Repository navigation
Conversation
…rops @deno/loader fetches every npm/jsr dependency through the global fetch, never retries, and swallows the failed download's error. One registry blip deep in a large tree then fails the build as "Could not find constraint '<root package>' in the list of packages" (or a missing module for a lost tarball) — the Stagehand package-matrix row flaked on exactly that. Wrap globalThis.fetch once on the first compile: GETs to the dependency hosts are retried on a network error, 429 or 5xx, and each failure is logged as base44.bundler.dependency_fetch_failed. Other requests pass through. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
VerificationReproduction against
Regression test: Full
Typecheck, Biome and knip are clean. Flake rate on |
🚀 Package Preview Available!Install this PR's preview build with npm: npm i @base44-preview/cli@0.1.33-pr.667.b65bd0bPrefer not to change any import paths? Install using npm alias so your code still imports npm i "base44@npm:@base44-preview/cli@0.1.33-pr.667.b65bd0b"Or add it to your {
"dependencies": {
"base44": "npm:@base44-preview/cli@0.1.33-pr.667.b65bd0b"
}
}
Preview published to npm registry — try new features instantly! |
Note
Description
@deno/loader0.5.0 downloads every dependency through the globalfetch, never retries (http_client.rs:// todo: implement retrying), and drops the failing download's error — so a single registry blip among the ~350 requests a large tree like Stagehand needs fails the whole compile, surfacing asCould not find constraint '<root package>' in the list of packagesor a bogusERR_MODULE_NOT_FOUND. This PR wrapsglobalThis.fetchonce per process so GETs to the dependency hosts are retried on a network error, 429 or 5xx, and logs every failed attempt so the real cause is visible. The same loader runs inbase44 publishand apper's bundler service, so this fixes user deploys as well as the flakytestStagehandpackage-matrix row in CI (3 of 29 Functions Compiler runs).Related Issue
None (CI flake: Functions Compiler run on main after #665)
Type of Change
Changes Made
packages/functions-compiler/src/dependency-fetch-retry.ts—installDependencyFetchRetry()wrapsglobalThis.fetchonce (idempotent via aninstalledflag);createRetryingFetch()retries twice (250 ms, then 1 s) on a network error, 429 or 5xx. A 404 is a real answer and is not retried; non-GET requests and requests to any non-dependency host (including the host's own API calls) pass through untouched. Response bodies are cancelled between attempts so a retried request does not leave its body dangling.base44.bundler.dependency_fetch_failedwith the URL, attempt number and HTTP status or error —warnwhile retries remain,erroron the last one — since the loader swallows the final failure.src/esbuild/deno-resolver.ts— installs the retry wrapper insetup(), before the Deno loader is created.src/fetch-guard.ts— exportsisDependencyHost(renamed fromisAllowedHost),requestUrland theFetchInputtype so the guard and the retry wrapper share one host allowlist.packages/functions-compiler/README.md— documents the wrapper, what it retries, and the new log event.Testing
npm test) — verified in CI; the e2e test needs network access and a coldDENO_DIRNew tests:
test/dependency-fetch-retry.e2e.test.ts— failsis-number's metadata once (503) while bundlingnpm:is-odd@3.0.1on a cold cache. Without the fix the build fails withCould not find constraint 'is-odd@3.0.1'; with it the bundle succeeds after exactly one retry.test/dependency-fetch-retry.test.ts— retries are bounded and return the last answer; a 404, a POST and a non-dependency host each go through exactly once.Checklist
docs/(AGENTS.md) if I made architectural changesAdditional Notes
Patching
globalThis.fetchis global by nature, but the wrapper is deliberately narrow — GET + dependency-host only — so a host embedding the compiler sees no change to its own traffic, and the existing fetch guard already scoped that host list. No release bump in this PR; that follows separately, as usual.🤖 Generated by Claude | 2026-10-19 09:13 UTC | b65bd0b