Relationships
#869 Local model source edit may not change the bundle cache key — rebuilt bundle shadowed by an older same-hash copy on a shared S3 datastore
Opened by mgreten · 6/27/2026· Shipped 6/29/2026
Thanks again for all the datastore work lately. I hit something while iterating on a local extension model and wanted to share it gently — I'm not certain I've got the mechanism exactly right, so please treat this as a hypothesis from one user's observations rather than a confident bug report.
What I observed
I edited a local model under extensions/models/ (added a method, bumped the version string in export const model). After the edit, the new method never became callable — swamp model method run <m> <newMethod> kept returning "Unknown method", and swamp model type describe showed the old method set.
Digging in, it looks like the bundle cache key didn't change when the source did:
swamp model evaluatedoesn't seem to recompile the bundle — it logs "No expressions to evaluate" and rewrites only the (thin) evaluated definition, whosemethods: {}is empty; the methods appear to come from the compiled bundle, resolved bytypeVersion.swamp doctor extensionsdoes recompile local models (I saw "Bundled … / Wrote bundle cache" with a new byte count), so the bundler itself works.- But the rebuilt bundle was written under the same hash directory as before (e.g.
bundles/<hash>/<model>.js), while the remote S3 copy at that hash still held the old bytes. Because the datastore pull restores the S3 copy, everymethod runended up with the stale bundle again — so the edit never "stuck".
If I'm reading it right, the bundle hash may not be derived from the method-body source content (a version bump + ~40 added lines kept the same hash). If so, two different bundle contents can collide on one cache key, and on a shared S3 datastore the older copy wins.
How I worked around it
I let doctor extensions rebuild the local bundle, then manually overwrote the S3 object at that hash with the fresh local bundle and updated its index entry's size/mtime so they matched. After a pull, the new method registered and survived subsequent runs. That's clearly a hack — I mention it only to confirm the diagnosis (content vs. cache-key mismatch), not as a suggested fix.
What might help (deferring entirely to your judgment)
Would it make sense for the bundle cache key to incorporate the compiled source content (or the model version) so an edit always produces a distinct bundle? Or for the loader to prefer a freshly-rebuilt local bundle over a same-hash remote copy? I don't have a strong view on the right layer — just flagging that today a local source edit can be silently shadowed by an older same-hash bundle, which is a tricky thing to debug.
No urgency, and I'm very happy to be corrected if I've misdiagnosed it. Glad to share exact repro steps, the before/after bundles, or logs whenever useful.
Environment
- swamp 20260626.202321.0-sha.1bf46b4f
- @swamp/s3-datastore (MinIO backend), namespace
agentic-tooling - Local model under
extensions/models/(not a pulled/published extension)
Possibly related: #867 (index/S3 reconciliation on pull).
Shipped
Click a lifecycle step above to view its details.
vcjdeboer commented 7/15/2026, 8:29:39 PM
Reopening with a fresh, clean repro — this still reproduces on swamp 20260711.205210.0-sha.c8b5c983 (2026-07-15), via a path that's specifically about model-instance version migration (not just the same-version bundle-cache-key collision), with no force-pull and no S3 datastore involved.
Clean repro
- Model instance
ingestof@vcjdeboer/session-ingest, created at typeVersion 2026.07.12.1. - Publish 2026.07.15.2, which ADDS a new method (
status) with anupgrades[]entry (identity migration). swamp extension update @vcjdeboer/session-ingest→ reports a real update:v2026.07.15.1 -> v2026.07.15.2, "1 updated". Lockfile + pulled code move to .15.2.swamp model get ingeststill showstypeVersion: 2026.07.12.1.swamp model method run ingest status→Unknown method 'status'(only the .12.1 method set is offered).- Bump the definition file's
typeVersionto .15.2 +swamp model evaluate ingest: the evaluated definition now reads .15.2, butstatusis still Unknown and the instance is still .12.1 — confirming methods come from the compiled bundle resolved by the instance typeVersion, which nothing advanced.
Notes
swamp extension updateupdates the extension (code + lockfile) but does not migrate existing model instances through theupgrades[]chain.swamp doctor extensionsin this build only lists (@vcjdeboer/session-ingest@2026.07.15.2 [pulled] 2 source(s)); it did not recompile/rebuild here (no "Bundled / Wrote bundle cache").- There is no
swamp model upgrade. The only non-destructive workaround found is overwriting the specific cached bundle.jsby hand; the clean path is delete+recreate, which loses the instance. - Corroborating signal: unrelated user models fail to load on every run with
Last upgrade toVersion X does not match model version Y(@alvagante/content-blog-post,@magistr/obsidian/vault) — same versioning-mismatch family.
Ask
A non-destructive swamp model upgrade <name> (or have extension update migrate existing instances via the upgrades[] chain) that advances an instance's typeVersion and reloads the new bundle, so new methods/reports become available without delete+recreate.
Sign in to post a ripple.