[9.2.0] Fix launching executables whose path can't be shortened on Windows (https://github.com/bazelbuild/bazel/pull/29921)#29984
Merged
iancha1992 merged 1 commit intoJun 25, 2026
Conversation
…azelbuild#29921) ### Description `AsExecutablePathForCreateProcess` shortens an executable's path with `GetShortPathNameW` so it fits `CreateProcessW`'s `MAX_PATH`-bound command line, and currently fails outright when shortening can't bring it under `MAX_PATH`. This change adds a fallback: it launches the executable through `CreateProcessW`'s _lpApplicationName_, which is not subject to the `MAX_PATH` limit, in extended-length (`\\?\`) form. Supplying _lpApplicationName_ also lifts the `MAX_PATH` limit from the executable part of _lpCommandLine_, so the original path is kept there as `argv[0]`. Shortening is still attempted first, so the change is a pure superset of the current behavior: paths that shorten today are launched unchanged, and only the currently-failing ones take the fallback. The fallback is limited to absolute, normalized paths to plain executables: - a batch file is not a valid _lpApplicationName_ as it must be run through a command interpreter, - neither is a non-normalized path because its `.`/`..` components would survive unresolved in the extended-length path. The fix relies on `\\?\` bypassing `MAX_PATH` at the path-parsing layer, **independently** of the _LongPathsEnabled_ registry value and the _longPathAware_ manifest. ### Motivation Fixes bazelbuild#19710. Avoid errors like: ``` ==================== Test output for //some/configuration/issues/invalidconfig:invalidconfig_test: ERROR(tools/test/windows/tw.cc:1307) ERROR: src/main/native/windows/process.cc(82): WaitableProcess::Create(C:\user\execroot\_main\bazel-out\x64_windows-fastbuild-ST-000000000001\bin\some\configuration\issues\invalidconfig\invalidconfig_test_\invalidconfig_test.exe.runfiles\_main\some\configuration\issues\invalidconfig\invalidconfig_test_\invalidconfig_test.exe): ERROR: src/main/native/windows/util.cc(292): AsExecutablePathForCreateProcess(C:\user\execroot\_main\bazel-out\x64_windows-fastbuild-ST-000000000001\bin\some\configuration\issues\invalidconfig\invalidconfig_test_\invalidconfig_test.exe.runfiles\_main\some\configuration\issues\invalidconfig\invalidconfig_test_\invalidconfig_test.exe): ERROR: src/main/native/windows/util.cc(262): GetShortPathNameW(\\?\C:\user\execroot\_main\bazel-out\x64_windows-fastbuild-ST-000000000001\bin\some\configuration\issues\invalidconfig\invalidconfig_test_\invalidconfig_test.exe.runfiles\_main\some\configuration\issues\invalidconfig\invalidconfig_test_\invalidconfig_test.exe): cannot shorten the path enough ERROR(tools/test/windows/tw.cc:1517) Failed to start test process (arg: C:\user\execroot\_main\bazel-out\x64_windows-fastbuild-ST-000000000001\bin\some\configuration\issues\invalidconfig\invalidconfig_test_\invalidconfig_test.exe.runfiles\_main\some\configuration\issues\invalidconfig\invalidconfig_test_\invalidconfig_test.exe) ================================================================================ ``` Shortening fails in two situations, both handled here: - 8dot3 short-name creation is disabled on the volume (common in containers, microsoft/Windows-Containers#507), so `GetShortPathNameW` is a no-op and a long runfiles executable path stays over `MAX_PATH`, - the path is nested so deeply that even fully 8dot3-shortened it still overflows `MAX_PATH`. Prior art: Rust's `std::process::Command` passes a verbatim `\\?\` path as _lpApplicationName_ for a >`MAX_PATH` executable and special-cases batch files the same way: - rust-lang/rust#87704, - rust-lang/rust#92519. ### Build API Changes No ### Checklist - [x] I have added tests for the new use cases (if any). - [ ] I have updated the documentation (if applicable). ### Release Notes RELNOTES: Fixed Bazel being unable to run a Windows executable whose path is too long to shorten under `MAX_PATH`, e.g. when 8dot3 short names are disabled (microsoft/Windows-Containers#507). Closes bazelbuild#29921. PiperOrigin-RevId: 937426905 Change-Id: Ia48d41e000622fc122d1b258ad15daa5018be75e
Wyverald
approved these changes
Jun 25, 2026
Merged
via the queue into
bazelbuild:release-9.2.0
with commit Jun 25, 2026
313773c
46 checks passed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
AsExecutablePathForCreateProcessshortens an executable's path withGetShortPathNameWso it fitsCreateProcessW'sMAX_PATH-bound command line, and currently fails outright when shortening can't bring it underMAX_PATH.This change adds a fallback: it launches the executable through
CreateProcessW's lpApplicationName, which is not subject to theMAX_PATHlimit, in extended-length (\\?\) form.Supplying lpApplicationName also lifts the
MAX_PATHlimit from the executable part of lpCommandLine, so the original path is kept there asargv[0].Shortening is still attempted first, so the change is a pure superset of the current behavior: paths that shorten today are launched unchanged, and only the currently-failing ones take the fallback.
The fallback is limited to absolute, normalized paths to plain executables:
./..components would survive unresolved in the extended-length path.The fix relies on
\\?\bypassingMAX_PATHat the path-parsing layer, independently of the LongPathsEnabled registry value and the longPathAware manifest.Motivation
Fixes #19710.
Avoid errors like:
Shortening fails in two situations, both handled here:
GetShortPathNameWis a no-op and a long runfiles executable path stays overMAX_PATH,MAX_PATH.Prior art: Rust's
std::process::Commandpasses a verbatim\\?\path as lpApplicationName for a >MAX_PATHexecutable and special-cases batch files the same way:process::Commandprogram without using the current directory rust-lang/rust#87704,process::Commandif necessary rust-lang/rust#92519.Build API Changes
No
Checklist
Release Notes
RELNOTES: Fixed Bazel being unable to run a Windows executable whose path is too long to shorten under
MAX_PATH, e.g. when 8dot3 short names are disabled (microsoft/Windows-Containers#507).Closes #29921.
PiperOrigin-RevId: 937426905
Change-Id: Ia48d41e000622fc122d1b258ad15daa5018be75e
Commit 4a80d43