Hive Hive
Sign in

Tuist generate fails when local package removed from declaration and tuist not cleaned

GitHub issue · Open

Metadata
Source
tuist/tuist #11002
Updated
Jun 11, 2026
Domains
Generated projects
Details

What happened?

When working on Tuist project containing Local Packages, tuist generate fails when one of the packages was removed. It seems to be some caching issue as problem is resolved by running tuist clean.

How do we reproduce it?

General reproduction:

  • Tuist project with local package dependencies
  • Commit A with Package_A in dependencies
  • Commit B with Package_A and Package_B in dependencies
  • Run tuist install; tuist generate in commit B
  • Switch to Commit A, run tuist install; tuist generate in commit A
  • tuist generate fails with Error Package.swift not found at path [...]/Packages/Package_B

Attaching minimal reproduction example: Tuist project with two local packages added via SPM. Repro steps in below example:

  • Checkout commit Integrate Package_B
  • Run tuist install; tuist generate
  • Checkout commit Integrate Package_A
  • Run tuist install; tuist generate

SPM_Install_Issue.zip

Error log

Error
Package.swift not found at path <redacted>/SPM_Install_Issue/Packages/Package_B
Sorry this didn’t work. Here’s what to try next:
If the error is actionable, address it
If the error is not actionable, let's discuss it in the Troubleshooting & how to
▸ If you are very certain it's a bug, file an issue
Check out the logs at <redacted>/state/tuist/sessions/62080655-1830-46E2-9BD6-4658B2357611/logs.txt

macOS version

26.4

Tuist version

4.195.11

Xcode version

26.4

Flights

Investigate, reproduce, or fix this item in an isolated repository. Each Flight preserves its outcome and agent session.

New Flights are paused Configure model inference, GitHub, and a sandbox provider to start another Flight. Existing results remain available below.
No Flights yet

Start a Flight and preserve its objective, outcome, and session here.

Comments
D
dosubot[bot] Jun 1, 2026

Thanks for the detailed repro steps, @TomaszLizer. This looks like a legitimate caching bug.

The root cause is that SPM’s workspace-state.json (stored in the scratch directory, typically .build) retains references to previously resolved packages even after they’re removed from Package.swift. When you switch from Commit B (with Package_B) back to Commit A (without Package_B), running tuist install doesn’t fully purge the stale entries from workspace-state.json, so tuist generate still tries to load Package_B and fails [1].

This class of issue has been addressed in CI/CD contexts before — for example, PR #10510 fixed stale .build cache by including Package.swift content in the cache key — but the local development workflow (switching branches with different package sets) still requires a manual tuist clean to clear the stale state.

As a workaround, tuist clean deletes the SPM scratch directory including workspace-state.json, which forces fresh resolution on the next run [2].

This does seem like a valid bug: tuist install (or tuist generate) should ideally detect that the resolved state references packages no longer declared in the manifest and invalidate or refresh accordingly, rather than requiring a manual clean step.

To reply, just mention @dosu.


Docs are dead. Just use Dosu.

Leave Feedback Ask Dosu about tuist Share Dosu with your team

T
TomaszLizer Jun 1, 2026

@dosu Expected behavior would be that tuist generate recognizes stale packages and do not include then in dependency resolution so that we do not waste time on clean and re-install which is very time consuming in projects with more external dependencies added via SPM. Most probably some graph sanitization would do the job to strip unused packages.

D
dosubot[bot] Jun 1, 2026

Agreed, @TomaszLizer — having tuist generate (or tuist install) automatically handle stale packages would be a much better experience than requiring a full tuist clean + re-install cycle.

From looking at the code, the issue is that Tuist treats workspace-state.json as read-only [1] and relies entirely on Swift Package Manager to manage it. When tuist install runs swift package resolve, SPM itself doesn’t always clean up entries for removed local packages. Then during tuist generate, the SwiftPackageManagerGraphLoader attempts to load every package referenced in workspace-state.json without first checking whether it still exists on disk or is still declared in Package.swift [1].

A fix could take the form of either:

  • A pre-validation step in the graph loader that filters out packages from workspace-state.json that are no longer declared in the current Package.swift, or
  • Automatically removing and re-resolving the SPM scratch directory when a mismatch is detected

Since this is a feature request / enhancement discussion that would benefit from input from the maintainers, I’d suggest posting this on the Tuist community forum under the Contributors or Help category, focusing on the proposed graph sanitization approach and the impact on developer workflows with many SPM dependencies. That way it can get visibility and feedback from the core team on the best path forward.

To reply, just mention @dosu.


Docs are dead. Just use Dosu.

Leave Feedback Ask Dosu about tuist Share Dosu with your team