Skip to content

Windows: Batch files cannot be path shortened enough #30431

Description

@ahewitson-ops

Description of the bug:

Performing a bazel test with a target whose executable is a batch file with a path above >256 characters will fail when either 8dot3name support is unavailable, or when the path cannot be shortened enough. While #19710 now ensures that .exe files are handled correctly (by prepending \\?\), Batch files are explicitly left out.

Which category does this issue belong to?

Core, Local Execution

What's the simplest, easiest way to reproduce this bug? Please provide a minimal example if possible.

Create a batch file with an extremely long (>256 character) path and wire up a bazel test to it, invoking it such that the test runner (tw.exe) runs it. You should also disable 8dot3name support on your file system during the test as it's the easiest way to ensure the path can never be shortened. fsutil 8dot3name set <drive> 1 will disable path shortening.

Which operating system are you running Bazel on?

Windows 11

What is the output of bazel info release?

release 8.6.0

If bazel info release returns development version or (@non-git), tell us how you built Bazel.

This is a development version that includes a backport of #29921 to try and mitigate long paths in our .ci infrastructure.

What's the output of git remote get-url origin; git rev-parse HEAD ?


If this is a regression, please try to identify the Bazel commit where the bug was introduced with bazelisk --bisect.

No response

Have you found anything relevant by searching the web?

No response

Any other information, logs, or outputs that you want to share?

Interestingly I have a fix for this on our local bazel fork that just passes the batch file to CreateProcessW and it works just fine. Providing that you also add the Manifest as Nwatkiss points out in this comment from a previous attempt at longpath fixing here. It's important to note that you cannot pass the batch file with a \\?\ prefix as cmd.exe apparently doesn't know what to do with it.

According to CreateProcessW documentation, any batch file being passed MUST "set lpApplicationName to cmd.exe and set lpCommandLine to the following arguments: /c plus the name of the batch file.".

I can raise a PR with a possible fix for this, but I'm unsure about tying functionality to undocumented support in Windows.

Activity

  1. fmeum commented on Jul 23, 2026

    @fmeum
    Collaborator

    Undocumented support that works in practice is better than no support - happy to prereview a PR!

  2. ahewitson-ops commented on Jul 23, 2026

    @ahewitson-ops
    ContributorAuthor

    I do love undocumented support!

    Here's the crux of the patch to src/main/native/windows/util.cc, the manifest changes are pretty trivial.

    diff --git a/src/main/native/windows/util.cc b/src/main/native/windows/util.cc
    index 872fb10e0e..3c404ca928 100644
    --- a/src/main/native/windows/util.cc
    +++ b/src/main/native/windows/util.cc
    @@ -314,15 +314,18 @@ wstring AsExecutablePathForCreateProcess(wstring path, wstring* quoted_path,
       // lpApplicationName: it is not subject to MAX_PATH, and providing it lifts
       // that limit from the executable part of CreateProcessW's lpCommandLine too.
       // This works only for a plain executable with an absolute, normalized path.
    -  if (!IsBatchFile(path)) {
    -    wstring native_path = path;
    -    std::replace(native_path.begin(), native_path.end(), L'/', L'\\');
    -    if (IsAbsoluteNormalizedWindowsPath(native_path)) {
    -      QuotePath(native_path, quoted_path);
    +  wstring native_path = path;
    +  std::replace(native_path.begin(), native_path.end(), L'/', L'\\');
    +  if (IsAbsoluteNormalizedWindowsPath(native_path)) {
    +    QuotePath(native_path, quoted_path);
    +    if (IsBatchFile(path)) {
    +      *extended_path = native_path;
    +    } else {
           *extended_path = wstring(L"\\\\?\\") + native_path;
    -      return L"";
         }
    +    return L"";
       }
    +
       return MakeErrorMessage(WSTR(__FILE__), __LINE__,
                               L"AsExecutablePathForCreateProcess", path, error);
     }
    

    Basically just sets the extended path for both Batch and Non-Batch files when the windows path is correctly absolute and normalized. The only difference being the \\?\ from the batch files. This'll probably break tests if we push it up at the moment but we should probably extend the tests for windows to include batch file usage like this.

  3. fmeum commented on Jul 23, 2026

    @fmeum
    Collaborator

    This looks good to me, could you send it as a PR? Let me know if you need help with the manifest or test setup.

  4. added
    area-WindowsWindows-specific issues and feature requests
    team-Local-ExecIssues and PRs for the Execution (Local) team
    on Jul 23, 2026
  5. ahewitson-ops commented on Jul 28, 2026

    @ahewitson-ops
    ContributorAuthor

    This looks good to me, could you send it as a PR? Let me know if you need help with the manifest or test setup.

    Added a PR here #30490

  6. added
    team-OSSIssues for the Bazel OSS team: installation, release processBazel packaging, website
    and removed
    team-Local-ExecIssues and PRs for the Execution (Local) team
    on Jul 28, 2026
  7. added
    P3We're not considering working on this, but happy to review a PR. (No assignee)
    and removed
    untriagedHas not yet been seen by appropriate subteam
    on Jul 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    P3We're not considering working on this, but happy to review a PR. (No assignee)area-WindowsWindows-specific issues and feature requeststeam-OSSIssues for the Bazel OSS team: installation, release processBazel packaging, websitetype: bug

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions