fix(core): improve windows path casing and validation#18607
fix(core): improve windows path casing and validation#18607yclian wants to merge 14 commits intogoogle-gemini:mainfrom
Conversation
* Preserve original path casing in Config and ProjectRegistry by removing forced lowercasing * Enhance WorkspaceContext to support case-insensitive path validation on Windows * Add unit tests for mixed-case path scenarios
|
Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA). View this failed invocation of the CLA check for more information. For the most up to date status, view the checks section at the bottom of the pull request. |
Summary of ChangesHello @yclian, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request addresses a critical bug in the Gemini CLI on Windows, specifically impacting users in MinGW environments with WSL paths. The core problem stemmed from an aggressive lowercase normalization of paths, which conflicted with Highlights
Changelog
Activity
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
There was a problem hiding this comment.
Code Review
This pull request addresses a critical issue with path handling on Windows, particularly for WSL paths, where incorrect case-normalization was causing validation failures. The changes involve removing forced lowercasing in Config and ProjectRegistry, and enhancing WorkspaceContext to perform case-insensitive path comparisons on Windows. The approach is sound and directly targets the root cause described.
The accompanying unit tests are valuable for preventing regressions. I've identified an issue in one of the new tests for ProjectRegistry that could cause it to fail on Windows and doesn't correctly verify the intended case-preservation behavior. My review includes a specific suggestion to correct this, which has been retained as it is a valid and important functional correction not covered by the provided rules.
| // helper normalizePath in this test file just resolves (no lowercase) | ||
| const normalizedKey = normalizePath(mixedCasePath); | ||
| expect(data.projects[normalizedKey]).toBe('myproject'); |
There was a problem hiding this comment.
The normalizePath helper function in this test file lowercases paths on Windows, which is the opposite of what this test aims to verify (case preservation). As a result, normalizedKey will be lowercased on Windows, while the key stored in data.projects will retain its original casing from mixedCasePath. This will cause data.projects[normalizedKey] to be undefined and the test to fail on Windows.
Additionally, the comment on line 129 is incorrect.
To fix this, you should get the expected key by resolving the path directly and remove the misleading comment.
| // helper normalizePath in this test file just resolves (no lowercase) | |
| const normalizedKey = normalizePath(mixedCasePath); | |
| expect(data.projects[normalizedKey]).toBe('myproject'); | |
| const expectedKey = path.resolve(mixedCasePath); | |
| expect(data.projects[expectedKey]).toBe('myproject'); |
|
Hi @galz10 - Just a heads-up that @spencer426 's recent commit 5e2f5df inadvertently resolved the immediate validation errors I was seeing by "aggressively" converting all Windows paths to lowercase. I believe the approach in this PR is still necessary. Spencer's fix relies on destructive normalization. While it enables path equality checks to pass, it mutates user paths to be entirely lowercase. Please let me know your thoughts: whether we should proceed with this PR or abandon it and move forward. |
* Preserve original path casing in Config and ProjectRegistry by removing forced lowercasing * Enhance WorkspaceContext to support case-insensitive path validation on Windows * Add unit tests for mixed-case path scenarios
…i into fix-wsl-path-validation
Summary
This fixes #18594.
Gemini CLI fails to validate WSL paths on Windows when running in a MinGW environment. All file operations fail with "Path not in workspace" errors, even though the path is clearly within the workspace.
The core issue: When paths are normalized to lowercase on Windows, fs.realpathSync() fails to resolve WSL UNC paths (e.g., \wsl.localhost\ubuntu...) because the actual filesystem uses mixed case (e.g., \wsl.localhost\Ubuntu...). When realpathSync() fails, it returns a truncated path in the error object, which then fails validation.
Details
Root cause
The issue is in
packages/core/src/utils/workspaceContext.ts, specifically in theisPathWithinRoot()method. On Windows,path.relative()performs case-sensitive string comparison for UNC/WSL paths, even though Windows filesystems are case-insensitive.When comparing:
\\wsl.localhost\Ubuntu-20.04\...(original case from user input)\\wsl.localhost\ubuntu-20.04\...(lowercase from stored workspace)The
path.relative()function treats these as different paths and returns..\..\.., causing the validation to fail.Breaking commits
This issue was likely introduced by these two commits that added lowercase path normalization on Windows:
5f569fa10(2026-01-27) - "refactor(core): centralize path validation and allow temp dir access for tools (refactor(core): centralize path validation and allow temp dir access for tools #17185)"toLowerCase()normalization inconfig.ts:18576fb3b0900(2026-02-06) - "Shorten temp directory (Shorten temp directory #17901)"normalizePath()method inprojectRegistry.ts:70-76that normalizes to lowercaseBoth commits normalized paths to lowercase for case-insensitive comparison on Windows, but this breaks WSL paths because
fs.realpathSync()requires exact filesystem casing to resolve UNC paths.The issue involves a chain of problems:
\\wsl.localhost\ubuntu\...) before filesystem operationsfs.realpathSync()fails because WSL paths are case-sensitive for UNC paths - the actual path is\\wsl.localhost\Ubuntu\...(capital U)realpathSync()fails withENOENT, the error object'se.pathcontains a truncated path (e.g.,.../developmentinstead of.../development/github.com/google-gemini/gemini-cli)path.relative()to return..\..\.., which fails the "within workspace" checkHow to Validate
Pre-Merge Checklist