Skip to content

fix(core): improve windows path casing and validation#18607

Closed
yclian wants to merge 14 commits intogoogle-gemini:mainfrom
yclian:fix-wsl-path-validation
Closed

fix(core): improve windows path casing and validation#18607
yclian wants to merge 14 commits intogoogle-gemini:mainfrom
yclian:fix-wsl-path-validation

Conversation

@yclian
Copy link

@yclian yclian commented Feb 9, 2026

  • 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

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 the isPathWithinRoot() 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:

  1. 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)"

    • Added toLowerCase() normalization in config.ts:1857
  2. 6fb3b0900 (2026-02-06) - "Shorten temp directory (Shorten temp directory #17901)"

    • Added normalizePath() method in projectRegistry.ts:70-76 that normalizes to lowercase

Both 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:

  1. Premature lowercase normalization: Paths are normalized to lowercase (e.g., \\wsl.localhost\ubuntu\...) before filesystem operations
  2. Failed path resolution: fs.realpathSync() fails because WSL paths are case-sensitive for UNC paths - the actual path is \\wsl.localhost\Ubuntu\... (capital U)
  3. Path truncation: When realpathSync() fails with ENOENT, the error object's e.path contains a truncated path (e.g., .../development instead of .../development/github.com/google-gemini/gemini-cli)
  4. Validation failure: The truncated path is then compared against the full workspace path, causing path.relative() to return ..\..\.., which fails the "within workspace" check

How to Validate

  • Navigate to a Git repository using a MinGW Bash environment.
  • Run Gemini with the prompt: "list the last 3 commits".

Pre-Merge Checklist

  • [] Updated relevant documentation and README (if needed)
  • Added/updated tests (if needed)
  • [] Noted breaking changes (if any)
  • Validated on required platforms/methods:
    • MacOS
      • npm run
      • npx
      • Docker
      • Podman
      • Seatbelt
    • Windows
      • npm run: Manual end-to-end verification completed
      • npx
      • Docker
    • Linux
      • npm run
      • npx
      • Docker
 > list last 5 commits
▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄✦ I will retrieve the last five commits from the repository to show the recent history.


╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ ✓  Shell git log -n 5 --oneline [current working directory \\wsl.localhost\Ubuntu-20.04\home\yclian\Development\github.com\google-gemini\gemini-cli] (Listing the last 5 comm… │
│                                                                                                                                                                                │
│ 97a4e62df (HEAD -> main, origin/main, origin/HEAD) feat(core): conditionally include ctrl+f prompt based on interactive shell setting (#18561)                                 │
│ 29a6aecff propagate abortSignal (#18477)                                                                                                                                       │
│ 92012365c fix(core): correct escaped interpolation in system prompt (#18557)                                                                                                   │
│ 802bcf4de refactor(cli): switch useToolScheduler to event-driven engine (#18565)                                                                                               │
│ 4a48d7cf9 feat(cli): truncate shell output in UI history and improve active shell display (#17438)                                                                             │
╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
✦ 97a4e62df (HEAD -> main) feat(core): conditionally include ctrl+f prompt based on interactive shell setting (#18561)
  29a6aecff propagate abortSignal (#18477)
  92012365c fix(core): correct escaped interpolation in system prompt (#18557)
  802bcf4de refactor(cli): switch useToolScheduler to event-driven engine (#18565)
  4a48d7cf9 feat(cli): truncate shell output in UI history and improve active shell display (#17438)

▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ > /about
▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄

╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│                                                                                                                                                                                    │
│ About Gemini CLI                                                                                                                                                                   │
│                                                                                                                                                                                    │
│ CLI Version                                                   0.29.0-nightly.20260203.71f46f116                                                                                    │
│ Git Commit                                                    b649fb50                                                                                                             │
│ Model                                                         auto-gemini-3                                                                                                        │
│ Sandbox                                                       no sandbox                                                                                                           │
│ OS                                                            win32                                                                                                                │
│ Auth Method                                                   gemini-api-key                                                                                                       │

ℹ A new version of Gemini CLI is available! 0.29.0-nightly.20260203.71f46f116 → 0.29.0-nightly.20260206.4ffc349c1
  Please run npm install -g @google/gemini-cli@latest to update

                                                                                                                                                                      ? for shortcuts
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

* 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
@yclian yclian requested a review from a team as a code owner February 9, 2026 07:16
@google-cla
Copy link

google-cla bot commented Feb 9, 2026

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.

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @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 fs.realpathSync's requirement for exact casing on WSL UNC paths. This led to path truncation and validation failures. The changes revert the premature lowercasing in key path handling utilities and enhance the workspace context to perform case-insensitive comparisons on Windows, ensuring robust and correct path validation across different casing conventions.

Highlights

  • Path Casing Preservation: Eliminated forced lowercasing of paths in Config and ProjectRegistry to ensure original casing is preserved, which is crucial for compatibility with certain file systems like WSL.
  • Enhanced Windows Path Validation: Improved WorkspaceContext to correctly validate paths on Windows, especially for WSL UNC paths, by handling case-insensitivity during path comparisons.
  • New Unit Tests: Introduced new unit tests to cover mixed-case path scenarios and explicitly verify that path casing is preserved and validation works as expected on Windows.
  • Critical Bug Fix: Resolved a critical issue (github.com/Path validation fails for WSL paths on Windows (MinGW) #18594) where Gemini CLI failed to validate WSL paths on Windows due to conflicts between premature lowercase path normalization and fs.realpathSync requirements.
Changelog
  • packages/core/src/config/config.test.ts
    • Added a new describe('isPathAllowed') block with a test case to verify that isPathWithinWorkspace is called with the original mixed-case path, ensuring casing preservation during path validation.
  • packages/core/src/config/config.ts
    • Removed the os import as it's no longer directly used in this file.
    • Modified the realpath helper function to remove the Windows-specific toLowerCase() call, allowing paths to retain their original casing.
  • packages/core/src/config/projectRegistry.test.ts
    • Added a new test case it('preserves path casing on Windows') to confirm that the ProjectRegistry stores project paths with their original casing, even though the short ID might be lowercase.
  • packages/core/src/config/projectRegistry.ts
    • Removed the os import.
    • Simplified the normalizePath method to only resolve the path, removing the Windows-specific toLowerCase() operation.
  • packages/core/src/utils/workspaceContext.test.ts
    • Added a new test it('should match paths case-insensitively on Windows') that explicitly mocks the platform to win32 and verifies that isPathWithinWorkspace correctly identifies paths within the workspace regardless of casing differences.
  • packages/core/src/utils/workspaceContext.ts
    • Added os import.
    • Modified the WorkspaceContext constructor to use fs.realpathSync on the targetDir to ensure the stored root path retains its canonical, filesystem-accurate casing.
    • Updated fullyResolvedPath to include Windows-specific logic for handling absolute input paths with incorrect casing, attempting fs.realpathSync directly or normalizing against the targetDir's case.
    • Modified isPathWithinRoot to normalize both the rootDirectory and pathToCheck to lowercase before calling path.relative on Windows, enabling case-insensitive comparison for validation.
Activity
  • Added/updated tests to cover new functionality and bug fixes.
  • Validated the changes on Windows using npm run.
Using Gemini Code Assist

The 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 /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

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 .gemini/ folder in the base of the repository. Detailed instructions can be found here.

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

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment on lines +129 to +131
// helper normalizePath in this test file just resolves (no lowercase)
const normalizedKey = normalizePath(mixedCasePath);
expect(data.projects[normalizedKey]).toBe('myproject');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

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.

Suggested change
// 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');

@gemini-cli gemini-cli bot added the area/core Issues related to User Interface, OS Support, Core Functionality label Feb 9, 2026
@gemini-cli gemini-cli bot added the priority/p1 Important and should be addressed in the near term. label Feb 9, 2026
@yclian
Copy link
Author

yclian commented Feb 22, 2026

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.

@yclian
Copy link
Author

yclian commented Feb 23, 2026

Hi @galz10, I need to walk back my last update. After a few more runs, I realized the problem (#18594) is still there. It only seemed to be working because, after a few trials, the Gemini CLI decided to work around things either via PowerShell or the temp folder.

* 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
@yclian yclian requested review from a team as code owners February 28, 2026 12:35
@yclian
Copy link
Author

yclian commented Mar 10, 2026

Might have been fixed by #21487 and #21639. Took a village!

@yclian yclian closed this Mar 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/core Issues related to User Interface, OS Support, Core Functionality priority/p1 Important and should be addressed in the near term.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Path validation fails for WSL paths on Windows (MinGW)

1 participant