✅ Expected Behavior
When I:
- Add a new entry to the
catalog in vlt.json, and
- Edit a workspace
package.json to switch a dep from a literal range (e.g. "^5.9.3") to "catalog:",
…running vlt install should rewrite the workspace dep edge in vlt-lock.json from dev ^5.9.3 ~npm~<pkg>@5.9.3 to dev catalog: ~npm~<pkg>@5.9.3, so future bumps to the catalog entry actually flow through to the workspace.
❌ Actual Behavior
vlt install reports added: 0, changed: 0, removed: 0 and:
- ✅ The lockfile's top-level
options.catalog snapshot does get updated to include the new entry.
- ❌ The workspace dep edge in
vlt-lock.json does not get rewritten. It still records the literal version (dev ^5.9.3 ~npm~typescript@5.9.3) instead of dev catalog: ~npm~typescript@5.9.3.
The two halves of the lockfile are now inconsistent: options.catalog lists typescript, but no workspace edge actually references the catalog. As a result, future edits to the catalog entry won't trigger any reinstall, defeating the whole point of cataloging the dep.
The only way I found to get the lockfile back into a consistent state was a full clean: rm vlt-lock.json && vlr wipe && vlt install.
🔄 Steps to Reproduce
mkdir vlt-catalog-bug && cd vlt-catalog-bug
cat > vlt.json <<'JSON'
{
"workspaces": ["packages/*"],
"catalog": {
"vitest": "^4.1.4"
}
}
JSON
cat > package.json <<'JSON'
{ "name": "vlt-catalog-bug", "private": true }
JSON
mkdir -p packages/a
cat > packages/a/package.json <<'JSON'
{
"name": "a",
"version": "0.0.0",
"devDependencies": {
"typescript": "^5.9.3",
"vitest": "catalog:"
}
}
JSON
vlt install
grep '"workspace.*typescript"' vlt-lock.json
# => "workspace~packages+a typescript": "dev ^5.9.3 ~npm~typescript@5.9.3"
# Now: add typescript to the catalog and switch the workspace dep to catalog:
cat > vlt.json <<'JSON'
{
"workspaces": ["packages/*"],
"catalog": {
"typescript": "^5.9.3",
"vitest": "^4.1.4"
}
}
JSON
cat > packages/a/package.json <<'JSON'
{
"name": "a",
"version": "0.0.0",
"devDependencies": {
"typescript": "catalog:",
"vitest": "catalog:"
}
}
JSON
vlt install
# {
# "add": [], "added": 0,
# "change": [], "changed": 0,
# "remove": [], "removed": 0
# }
grep -A 5 '"options"' vlt-lock.json
# "options": {
# "catalog": {
# "typescript": "^5.9.3", <-- snapshot WAS updated
# "vitest": "^4.1.4"
# }
# },
grep '"workspace.*typescript"' vlt-lock.json
# "workspace~packages+a typescript": "dev ^5.9.3 ~npm~typescript@5.9.3"
# ^^^^^^^ should be `catalog:`
🌍 Environment
- OS: darwin v24.15.0
- Node: v24.15.0
- vlt: 1.0.0-rc.27
🔄 Frequency
Always - Happens every time
📈 Regression Check
Looks like a regression / incomplete fix of:
Both were closed as completed but this exact scenario (catalog added in vlt.json + workspace package.json switched to catalog:) still requires a full clean to take effect.
🛠️ Workaround
rm vlt-lock.json && vlr wipe && vlt install
After this, the workspace edge correctly shows dev catalog: ~npm~typescript@5.9.3 and options.catalog matches.
📎 Additional Context
Hit while migrating typescript to a catalog entry in a real monorepo (vltpkg/vlt.io-2) — every workspace already resolved to the same typescript@5.9.3, so the goal was to centralize the spec without changing resolved versions. The package.json edits were correct and vlt install exited cleanly, but the lockfile still recorded the old literal specs on every workspace edge. Took a wipe to notice.
✅ Expected Behavior
When I:
cataloginvlt.json, andpackage.jsonto switch a dep from a literal range (e.g."^5.9.3") to"catalog:",…running
vlt installshould rewrite the workspace dep edge invlt-lock.jsonfromdev ^5.9.3 ~npm~<pkg>@5.9.3todev catalog: ~npm~<pkg>@5.9.3, so future bumps to the catalog entry actually flow through to the workspace.❌ Actual Behavior
vlt installreportsadded: 0, changed: 0, removed: 0and:options.catalogsnapshot does get updated to include the new entry.vlt-lock.jsondoes not get rewritten. It still records the literal version (dev ^5.9.3 ~npm~typescript@5.9.3) instead ofdev catalog: ~npm~typescript@5.9.3.The two halves of the lockfile are now inconsistent:
options.catalogliststypescript, but no workspace edge actually references the catalog. As a result, future edits to the catalog entry won't trigger any reinstall, defeating the whole point of cataloging the dep.The only way I found to get the lockfile back into a consistent state was a full clean:
rm vlt-lock.json && vlr wipe && vlt install.🔄 Steps to Reproduce
🌍 Environment
🔄 Frequency
Always - Happens every time
📈 Regression Check
Looks like a regression / incomplete fix of:
vlt idoes not update lockfile #892 — "[BUG] updating catalog in vlt.json and runningvlt idoes not update lockfile" (closed completed 2025-06-24)package.jsonmanually, changes are not applied withvlt install#1180 — "[BUG] After updatingpackage.jsonmanually, changes are not applied withvlt install" (closed completed 2025-11-27)Both were closed as completed but this exact scenario (catalog added in
vlt.json+ workspacepackage.jsonswitched tocatalog:) still requires a full clean to take effect.🛠️ Workaround
After this, the workspace edge correctly shows
dev catalog: ~npm~typescript@5.9.3andoptions.catalogmatches.📎 Additional Context
Hit while migrating
typescriptto a catalog entry in a real monorepo (vltpkg/vlt.io-2) — every workspace already resolved to the sametypescript@5.9.3, so the goal was to centralize the spec without changing resolved versions. The package.json edits were correct andvlt installexited cleanly, but the lockfile still recorded the old literal specs on every workspace edge. Took a wipe to notice.