aspire restore skips re-restore when an older CLI replaced the integration assets, silently reusing the old code generator
- Dominant language
- C#
- Stars
- 6.3k
- Forks
- 991
- Avg merge
- 2d 15h
- Merged PRs (30d)
- 196
Description
# `aspire restore` silently runs the previous CLI version's TypeScript code generator after a version switch
## Summary
`aspire restore` rewrites the generated `IntegrationRestore.csproj` with the current CLI's package version, but does not re-restore or rebuild it. The previously built generator assembly stays in `bin/`, so code generation runs with the *old* CLI's generator while reporting success. Any codegen fix in a newer CLI silently does not apply until the user deletes `.aspire/` by hand.
## Repro
A TypeScript AppHost. Two CLI versions installed — released `13.5.1` and a dogfood build `13.6.0-pr.19577.gfa0aea2c` (which contains the #19577 codegen fix).
```bash
# 1. clean generate with the newer CLI -> correct output
rm -rf .aspire && aspire-13.6.0-pr restore
# 2. generate with the older CLI -> old (buggy) output, as expected
aspire-13.5.1 restore
# 3. generate with the newer CLI again -> STILL the old buggy output
aspire-13.6.0-pr restore
```
Step 3 prints `✅ SDK code restored successfully` with no warning.
## Observed state after step 3
| What | Value |
|---|---|
| `integration-restore/IntegrationRestore.csproj` `PackageReference` | `13.6.0-pr.19577.gfa0aea2c` ✅ rewritten |
| `RestoreAdditionalProjectSources` | points at the new hive ✅ |
| `integration-restore/obj/project.assets.json` | `Aspire.Hosting.CodeGeneration.TypeScript/13.5.1` ❌ |
| `integration-restore/bin/Debug/net10.0/Aspire.Hosting.CodeGeneration.TypeScript.dll` | `13.5.1+69db530a…` ❌ |
| generated `.aspire/modules/aspire.mts` | old generator's output ❌ |
| exit / message | success, no warning ❌ |
File mtimes show the ordering:
```
09:57:36 IntegrationRestore.csproj <- rewritten to 13.6.0-pr
09:57:19 obj/project.assets.json <- 17s EARLIER, still 13.5.1
07:54:51 obj/aspire-restore.stamp <- hours old, never refreshed
2026-08-20 19:03 bin/.../CodeGeneration.TypeScript.dll <- 13.5.1 package content
```
`obj/aspire-restore.stamp` never being refreshed looks like the gate: the CLI decides the integration restore is up to date and skips it, despite having just written a csproj that pins a different package version. `.codegen-hash` *does* change, so code generation itself re-runs — it just runs the stale generator.
The new package is present and resolvable (`~/.aspire/hives/pr-19577/packages/Aspire.Hosting.CodeGeneration.TypeScript.13.6.0-pr.19577.gfa0aea2c.nupkg`), so this is not a resolution failure.
## Asymmetry
Going **down** (13.6.0-pr → 13.5.1) *does* rebuild correctly — csproj, `project.assets.json`, and `bin/` all move to 13.5.1. Only the second switch fails to rebuild, which is what makes it easy to miss.
## Why it matters
The failure mode is invisible and actively misleading. Verifying a codegen fix by installing a PR build and re-running `aspire restore` reports success and produces the unfixed output — which reads as "the fix does not work." It cost me a false negative while validating #19577 against the sample from #19507.
Deleting `.aspire/modules` is **not** sufficient — codegen re-runs against the stale generator in `.aspire/integrations/`. Only `rm -rf .aspire` works.
## Suggestions
- Include the CLI / codegen package version in whatever `obj/aspire-restore.stamp` gates on, so a version change forces re-restore and rebuild.
- Or compare the resolved version in `project.assets.json` against the version just written to the csproj, and re-restore on mismatch.
- At minimum, warn when the built generator assembly's version differs from the running CLI's, instead of reporting plain success.
## Environment
- Aspire CLI `13.5.1+69db530a4816698cf1d5fa4557933e0ac4f127c6` and `13.6.0-pr.19577.gfa0aea2c`
- linux-x64 (WSL2), .NET SDK with net10.0 target
- Dogfood build installed via `eng/scripts/get-aspire-cli-pr.sh 19577`
## Related
- #19577 / #19507 — the codegen fix whose verification this masked.
- #19503 — also a CLI/codegen version-skew failure, but a different root cause (frozen `Aspire.TypeSystem` contract producing `MissingMethodException` at bind time). This one is a build-staleness problem in `integration-restore`, and fails silently rather than throwing.
Contributor guide
Research direction
Reproduce the three-step CLI version switch, then inspect integration-restore/IntegrationRestore.csproj, obj/project.assets.json, obj/aspire-restore.stamp, .codegen-hash, and the generated assembly under bin/. Trace why the stamp permits reuse after the package version changes. Done means switching versions refreshes the resolved package and built generator so generated output comes from the current CLI rather than silently reusing the old code.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- csharp, typescript
- Domain
- build-system, cli, tooling
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 58/100