rushstack icon indicating copy to clipboard operation
rushstack copied to clipboard

[rush] rush build with build cache enabled will crash when a symlink file links to a directory

Open LPegasus opened this issue 3 weeks ago • 2 comments

Summary

When I run rush build, the error likes:

2025/11/27 10:53:38 Error calculating the state of the repo. (inner error: Error: git --no-optional-locks exited with code 128:
2025/11/27 10:53:38 fatal: Unable to hash <my_symlink_file>
2025/11/27 10:53:38 
2025/11/27 10:53:38     at spawnGitAsync (*/common/temp/install-run/@[email protected]/node_modules/@rushstack/package-deps-hash/lib/getRepoState.js:227:15)
2025/11/27 10:53:38     at async hashFilesAsync (*/common/temp/install-run/@[email protected]/node_modules/@rushstack/package-deps-hash/lib/getRepoState.js:266:30)
2025/11/27 10:53:38     at async getDetailedRepoStateAsync (*/common/temp/install-run/@[email protected]/node_modules/@rushstack/package-deps-hash/lib/getRepoState.js:340:36)
2025/11/27 10:53:38     at async Promise.all (index 0)
2025/11/27 10:53:38     at async tryGetSnapshotAsync (*/common/temp/install-run/@[email protected]/node_modules/@microsoft/rush-lib/dist/commons.js:22694:89)
2025/11/27 10:53:38     at async PhasedScriptAction._runInitialPhasesAsync (*/common/temp/install-run/@[email protected]/node_modules/@microsoft/rush-lib/dist/commons.js:21058:33)
2025/11/27 10:53:38     at async PhasedScriptAction.runAsync (*/common/temp/install-run/@[email protected]/node_modules/@microsoft/rush-lib/dist/commons.js:21032:37)
2025/11/27 10:53:38     at async PhasedScriptAction.onExecuteAsync (*/common/temp/install-run/@[email protected]/node_modules/@microsoft/rush-lib/dist/commons.js:19507:16)
2025/11/27 10:53:38     at async PhasedScriptAction._executeAsync (*/common/temp/install-run/@[email protected]/node_modules/@rushstack/ts-command-line/lib/providers/CommandLineAction.js:64:9)
2025/11/27 10:53:38     at async RushCommandLineParser.onExecuteAsync (*/common/temp/install-run/@[email protected]/node_modules/@rushstack/ts-command-line/lib/providers/CommandLineParser.js:262:13)). Continuing without diffing files.
2025/11/27 10:53:38 Analyzing repo state... DONE (1.31 seconds)
2025/11/27 10:53:38 
2025/11/27 10:53:38 Selected 15 operations:
2025/11/27 10:53:38   *** (build)
2025/11/27 10:53:38   *** (build2)
2025/11/27 10:53:38   *** (pre-build)
2025/11/27 10:53:38   *** (build)
2025/11/27 10:53:38   *** (build2)
2025/11/27 10:53:38   *** (pre-build)
2025/11/27 10:53:38   *** (build)
2025/11/27 10:53:38 
2025/11/27 10:53:38 Executing a maximum of 128 simultaneous processes...
2025/11/27 10:53:38 Error: Build cache is only supported if running in a Git repository. Either disable the build cache or run Rush in a Git repository.
2025/11/27 10:53:38 rush build - Errors! (1.44 seconds)

Repro steps

  1. Create a symlink to a directory.
  2. Commit the symlink file into Git.
  3. Run rush build

Expected result: Get a better error message or track the real path directory files to calculate cache entry id.

Details

I traced the error code and found the cause of the error as follows:

  1. git ls-tree lists symlink files.

  2. git hash-object appears to treat symlinks to directories as actual directories, causing the error. (I'm not very sure how git hash-object works)

I think there are two possible solutions here:

  1. Clearly state the cause of the error, specify that symlinks to directories are not supported, and suggest adding the symlink to .gitignore or incrementalBuildIgnoredGlobs.

  2. Track files within the symlink directory and recursively compute the hash for the realpath files, avoiding circular recursion.

Standard questions

Please answer these questions to help us investigate your issue more quickly:

Question Answer
@microsoft/rush globally installed version? 5.155.1
rushVersion from rush.json? 5.155.1
useWorkspaces from rush.json? Yes
Operating system? Mac
Would you consider contributing a PR? Yes
Node.js version (node -v)? 22.20.0

LPegasus avatar Dec 03 '25 07:12 LPegasus

This is an interesting edge case. A better error message makes sense, or handling it correctly would be better. The file mode is 120000 and git ls-tree returns a hash. @LPegasus, can you provide a minimal repro?

iclanton avatar Dec 03 '25 19:12 iclanton

This is an interesting edge case. A better error message makes sense, or handling it correctly would be better. The file mode is 120000 and git ls-tree returns a hash. @LPegasus, can you provide a minimal repro?

Sure. https://github.com/LPegasus/rushstack-issue-5479 Run rush update && rush test to see the error.

LPegasus avatar Dec 04 '25 03:12 LPegasus

With #5500 , Rush will now categorize symlinks separately from files, and will therefore be able to ignore them if they are committed. If there are local changes to them returned by git status there will still be breaks, because git status does not return mode information about affected files.

dmichon-msft avatar Dec 12 '25 23:12 dmichon-msft

Hi, @dmichon-msft . Thank you for your fix of the symlink crash!

The scenario where I encountered the issue was not about committing symlinks to the git repository, but rather that during the deployment build process, symlinks are generated. These symlinks are not included in the .gitignore, causing rush build to report an error and exit.

I understand that the fix for #5500 involves excluding symlinks from the hash key calculation process. This may potentially mask some issues related to incorrect build cache hits. Therefore, I was wondering if there could be a feature that forces an error when symlink files are detected?

I am not sure if scenarios where build dependencies leak in some manner are something rush.js needs to detect. For example, another recent case of build dependency leakage involved a project using tsc --build with reference projects, which detached the build project's dependencies graph from rush.js and led to incorrect cache hits. Perhaps this type of issue is difficult to systematically prevent within rush.js.

LPegasus avatar Dec 17 '25 15:12 LPegasus