Relationships
#2354 Pulled extensions log a false 'bundle could not be regenerated' warning on every load and serve reload
Opened by stack72 · 9/22/2026· Shipped 9/22/2026
Description
Every load of pulled extensions logs a warn-level line per extension file:
Using cached bundle for "vpc.ts" — source may have changed but bundle could not be regeneratedNothing is wrong with these bundles, and no regeneration was attempted. The message was written for a rebundle-failure fallback. Pulled extensions now reach the same flag through a deliberate cache-trust path, so the wording is false for them.
It is loud in practice. With @swamp/aws/ec2 and @swamp/s3-datastore pulled (113 types), swamp serve printed 113 of these at startup and 113 more on every hot-reload: 1,469 lines over one startup and 12 SIGHUPs. That was observed while reproducing swamp-club#2340. Operators reading serve logs will take it as a bundling failure. This is the same kind of problem as swamp-club#2318: a harmless line that reads like an error.
Cause
ExtensionLoader.bundleWithCache() (src/domain/extensions/extension_loader.ts) returns fromCache: true in two unrelated situations:
- Deliberate trust of a pulled extension's existing bundle. When
trustPulledCacheis set, the bundle exists on disk and the file is underpulled-extensions/, it returns the cached bundle without spawningdeno bundle. This was added by ff430b10 (#1389) as a cold-start optimisation of about 27s for @swamp/aws/ec2. Bothload()call sites passtrustPulledCache: true. - Real rebundle failure.
deno bundlethrew and a previous bundle exists. It already logsRebundle failed for <file>, using cached bundle: <error>(warn, or debug for expected failures) before returning (15cd7fdc, swamp-club#265).
Both load() call sites (index-only around line 255 and full load around line 300) warn on any fromCache. So case 1 always emits a false "could not be regenerated", and case 2 emits a second, less specific warning after the accurate one.
Suggested fix
- Have
BundleResultsay why it came from cache, for examplecacheReason: "trusted-pulled" | "rebundle-failed". - Stop warning at the
load()call sites. The trusted-pulled case needs no log, or at most a debug line. The rebundle-failed case is already covered by the specific warning insidebundleWithCache. - Add unit tests for both
load()paths: a pulled extension with an existing bundle loads with no warn record, and a failing rebundle with an existing bundle emits exactly one warn record carrying the error. The log-capture pattern added for swamp-club#2318 inextension_loader_test.tsfits here.
Related: redundant work on every serve reload (note, not required for this fix)
The per-reload repetition comes from createExtensionDiscoverer (src/serve/extension_reload.ts), which performServeReload runs on every reload. It calls loader.load() over all pulled extension dirs with skipAlreadyRegistered: true. load() reads, cache-bundles and imports every file before it can skip the already-registered types. With @swamp/aws/ec2 that is about 118 MB of bundles read, hashed and imported per reload, to find nothing new.
Since swamp-club#2340 (PR 2549) those imports are content-addressed, so they reuse existing modules and no longer leak heap. The cost is time and I/O, not memory. Checking registration before bundling and importing would make serve reloads touch only genuinely new extensions. That could be done here or split into its own issue.
Steps to Reproduce
swamp repo init, thenswamp extension pull @swamp/aws/ec2- Start
swamp serve --hot-reload, or run any command that rescans the extension catalog - Observe one
Using cached bundle ... could not be regeneratedwarning per pulled model file kill -HUP <serve pid>and observe the full set again on every reload
Environment
- swamp:
20260922.162335.0-sha.1ac2f012and a local build of main at PR 2549 - macOS (darwin), MinIO-backed
@swamp/s3-datastore
Shipped
Click a lifecycle step above to view its details.
Sign in to post a ripple.