Hive Hive
Sign in

Path.relativeToCurrentFile invalidate cache

GitHub issue · Open

Metadata
Source
tuist/tuist #7659
Updated
Jun 11, 2026
Domains
Cache
Details

What happened?

Using Path.relativeToCurrentFile results in the callerPath being appended with the value from #file, which is the absolute path to the file, which in turn invalidates the manifest cache if the project folder has been moved (or created from separate directory on CI Job)

It seems more correct to first convert the path to relativeWorkspace before writing #file to callerPath.

How do we reproduce it?

Error log

macOS version

Tuist version

4.50.2

Xcode version

16

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 9, 2025

Hi @Ernest0-Production! I’m Dosu and I’m helping the tuist team.

The behavior you’re seeing is expected: Path.relativeToCurrentFile uses the absolute path from #file as callerPath, so when the project folder moves (like on CI), the resolved path changes and the cache invalidates. This isn’t an explicit cache invalidation—it’s a side effect of how the path resolution and hashing work, since the resolved absolute path depends on the file’s location at build time. This design ensures cache integrity but can cause issues in environments where the project directory changes location frequently, like CI jobs docs code.

There aren’t existing tickets or discussions directly about this, but some teams use workarounds like symlinking cache directories or setting a custom XDG_CACHE_HOME to help manage cache reuse across CI runs. Another approach is to store the manifest cache within the project directory so it can be cleaned up with the workspace community thread.

You can reproduce the issue by moving your project directory or running builds in different locations (e.g., on CI), which will cause the resolved paths—and thus the cache keys—to change.

If you want to avoid this, consider whether you can use a different path type (like relative to manifest or root) for resources that shouldn’t be tied to the source file’s location, or adopt one of the cache management workarounds above.

To reply, just mention @dosu.


Docs are dead. Just use Dosu.

Leave Feedback Ask Dosu about tuist Share Dosu with your team

P
pepicrft Jun 11, 2025

@Ernest0-Production, where are you using that path in your manifests? For attributes that represent a reference to a file, Tuist hashes the file itself, not the path, so it doesn’t matter its value.

EP
Ernest0-Production Jun 18, 2025

@pepicrft I mean that the resulting Workspace/Project/Target models, which contain in their Path variables (sources, resources, etc.), where callerPath is an absolute string, makes the final Codable model not reusable if the project is cloned into a parent directory with a new name

P
pepicrft Jun 19, 2025

I’m a bit confused. Once those paths are resolved to absolute paths, what we hash is the file/directory they point to, not the path itself, so unless I’m missing something, resolving the path to an absolute path at manifest compilation-time should have no effect in the caching.

I think I’m missing something here 😬

EP
Ernest0-Production Aug 18, 2025

Hello again! @pepicrft

I did some research on the problem I was having and realized that the main problem was actually that the path to the cached manifest was being generated from the hash sum of the absolute manifest path to Project.swift manifest.

I think this solution is not good enough, because it will lead to redundant creation of cache files for each workspace folder (for example, when running on CI in separate workspace).

https://github.com/tuist/tuist/blob/b5dbe5ab4f88025ef4d7a5165453868485d7eee7/Sources/TuistLoader/Loaders/CachedManifestLoader.swift#L237-L242


I think it would be more optimal to generate the hash sum from the contents of the swift manifest file. (for example using ContentHasher.hash(path:))

The same applies to the formation of the path to the ProjectDescriptionHelpers framework

P
pepicrft Aug 19, 2025

Thanks @Ernest0-Production for debugging this one. If you are up for it, feel free to go ahead with a contribution. Our binary cache functionality also does content-based hashing, so you might be able to reuse the logic from there.

G
gmazzo Jul 8, 2026

FYI I just faced this issue, and workaround by adding this ad-hoc fix in our project:

// assumed the .swift file is located under `Tuist/ProjectDescriptionHelpers/`
private let rootDir = URL(filePath: #file).appending(path: "../..").standardized.absoluteURL.path()
extension Path {
static func relativeToCurrentFile(_ pathString: String, callerPath: StaticString = #file) -> Path {
.relativeToRoot(URL(filePath: "\(callerPath)")
.deletingLastPathComponent()
.appending(path: pathString)
.absoluteURL
.path()
.replacingOccurrences(of: rootDir, with: ""))
}
}

Note

It’s not just cache invalidation, if you have multiple git worktrees, they endup resolving to the wrong worktree absolute path. If you have checkout a branch were those files does not exists, the generation will fail.