Fix launching executables whose path can't be shortened on Windows#29921
Closed
rdesgroppes wants to merge 2 commits into
Closed
Fix launching executables whose path can't be shortened on Windows#29921rdesgroppes wants to merge 2 commits into
rdesgroppes wants to merge 2 commits into
Conversation
rdesgroppes
added a commit
to DataDog/datadog-agent-buildimages
that referenced
this pull request
Jun 22, 2026
### What does this PR do? Enable NTFS 8.3 short-name creation on the container scratch volume at startup, via `fsutil 8dot3name set C: 0` in the entrypoint. The registry key from #1212 is dropped because it is now superseded and provably inert for the scratch volume. ### Motivation #1212 set `NtfsDisable8dot3NameCreation` to 0 in the image, betting the SYSTEM-hive value would travel with the layers. It **does** travel, but a container's fresh scratch volume surprisingly still comes up disabled at runtime: ``` The volume state is: 1 (8dot3 name creation is DISABLED) The registry state is: 0 (8dot3 name creation is ENABLED on all volumes) Based on the above settings, 8dot3 name creation is ENABLED on "C:" ``` `fsutil` **mistakenly** reports ENABLED after the registry override, yet freshly created files still get no 8.3 alias, so `GetShortPathNameW` stays a no-op and Bazel still cannot shorten long paths (bazelbuild/bazel#19710), root cause of [#incident-56436](https://dd.enterprise.slack.com/archives/C0BBPAV0J20). #1212 also anticipated that a build-time `fsutil 8dot3name set` would not persist, which a test image confirmed: the build volume flips to state 0, but a container started from that image is back to state 1. Per microsoft/Windows-Containers#507 and Microsoft Q&A[^1], the per-volume flag only takes hold across an unmount/remount and is not carried by image layers, so it must be (re)applied at runtime. The entrypoint is the earliest such point, ahead of any build. ### Possible Drawbacks / Trade-offs `fsutil 8dot3name set` runs on every container start, but it is a cheap per-volume metadata write. As in #1212, it only affects files created afterwards, which covers the runtime-created output base. ### Additional Notes Validated by DataDog/datadog-agent#52500 against this image: `bazel:test:windows-amd64` is green with the runtime override removed. There's work in progress we'll monitor to remove the workaround: - bazelbuild/bazel#29921. [^1]: of which: - https://learn.microsoft.com/en-us/answers/questions/1406321/enable-8dot3-name-creation-for-volume-c-in-windows - https://learn.microsoft.com/en-us/answers/questions/2455648/8-3-filename-support - etc.
rdesgroppes
added a commit
to DataDog/datadog-agent-buildimages
that referenced
this pull request
Jun 22, 2026
### What does this PR do? Enable NTFS 8.3 short-name creation on the container scratch volume at startup, via `fsutil 8dot3name set C: 0` in the entrypoint. The registry key from #1212 is dropped because it is now superseded and provably inert for the scratch volume. ### Motivation #1212 set `NtfsDisable8dot3NameCreation` to 0 in the image, betting the SYSTEM-hive value would travel with the layers. It **does travel**, but a container's fresh scratch volume surprisingly still comes up disabled at runtime despite `fsutil` output: ``` The volume state is: 1 (8dot3 name creation is DISABLED) The registry state is: 0 (8dot3 name creation is ENABLED on all volumes) Based on the above settings, 8dot3 name creation is ENABLED on "C:" ``` `fsutil` **mistakenly** reports ENABLED after the registry override, yet freshly created files **still get no 8.3 alias**, so `GetShortPathNameW` stays a no-op and Bazel still cannot shorten long paths (bazelbuild/bazel#19710), root cause of [#incident-56436](https://dd.enterprise.slack.com/archives/C0BBPAV0J20). #1212 also anticipated that a build-time `fsutil 8dot3name set` would not persist, which a test image confirmed: the build volume flips to state 0, but a container started from that image is back to state 1. Per microsoft/Windows-Containers#507 and Microsoft Q&A[^1], the per-volume flag only takes hold across an unmount/remount and is not carried by image layers, so it must be (re)applied at runtime. => The entrypoint is the earliest such point, ahead of any build. ### Possible Drawbacks / Trade-offs `fsutil 8dot3name set` runs on every container start, but it is a cheap per-volume metadata write. As in #1212, it only affects files created afterwards, which covers the runtime-created output base. ### Additional Notes Validated by DataDog/datadog-agent#52500 against this image: `bazel:test:windows-amd64` is green with the runtime override removed. There's work in progress we'll monitor to remove the workaround: - bazelbuild/bazel#29921. [^1]: of which: - https://learn.microsoft.com/en-us/answers/questions/1406321/enable-8dot3-name-creation-for-volume-c-in-windows - https://learn.microsoft.com/en-us/answers/questions/2455648/8-3-filename-support - etc.
rdesgroppes
added a commit
to DataDog/datadog-agent-buildimages
that referenced
this pull request
Jun 22, 2026
### What does this PR do? Enable NTFS 8.3 short-name creation on the container scratch volume at startup, via `fsutil 8dot3name set C: 0` in the entrypoint. The registry key from #1212 is dropped because it is now superseded and provably inert for the scratch volume. ### Motivation #1212 set `NtfsDisable8dot3NameCreation` to 0 in the image, betting the SYSTEM-hive value would travel with the layers. It **does travel**, but a container's fresh scratch volume surprisingly still comes up disabled at runtime despite `fsutil` output: ``` The volume state is: 1 (8dot3 name creation is DISABLED) The registry state is: 0 (8dot3 name creation is ENABLED on all volumes) Based on the above settings, 8dot3 name creation is ENABLED on "C:" ``` `fsutil` **mistakenly** reports ENABLED after the registry override, yet freshly created files **still get no 8.3 alias**, so `GetShortPathNameW` stays a no-op and Bazel still cannot shorten long paths (bazelbuild/bazel#19710), root cause of [#incident-56436](https://dd.enterprise.slack.com/archives/C0BBPAV0J20). #1212 also anticipated that a build-time `fsutil 8dot3name set` would not persist, which a test image confirmed: the build volume flips to state 0, but a container started from that image is back to state 1. Per microsoft/Windows-Containers#507 and Microsoft Q&A[^1], the per-volume flag only takes hold across an unmount/remount and is not carried by image layers, so it must be (re)applied at runtime. => The entrypoint is the earliest such point, ahead of any build. ### Possible Drawbacks / Trade-offs `fsutil 8dot3name set` runs on every container start, but it is a cheap per-volume metadata write. As in #1212, it only affects files created afterwards, which covers the runtime-created output base. ### Additional Notes Validated by DataDog/datadog-agent#52500 against this image: `bazel:test:windows-amd64` is green with the runtime override removed. There's work in progress we'll monitor to remove the workaround: - bazelbuild/bazel#29921. [^1]: of which: - https://learn.microsoft.com/en-us/answers/questions/1406321/enable-8dot3-name-creation-for-volume-c-in-windows - https://learn.microsoft.com/en-us/answers/questions/2455648/8-3-filename-support - etc.
fmeum
approved these changes
Jun 22, 2026
fmeum
left a comment
Collaborator
There was a problem hiding this comment.
Nice fix, this looks pretty simple and doesn't require any manifest patching.
Collaborator
|
FYI @meteorcloudy for when you are back |
### 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. 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).
cbb4d49 to
812a275
Compare
gh-worker-dd-mergequeue-cf854d Bot
pushed a commit
to DataDog/datadog-agent
that referenced
this pull request
Jun 23, 2026
…2500) ### What does this PR do? Add a preflight check that creates a temp file whose name exceeds 8.3 limits and compare its long name (`%%~nxi`) against its short name (`%%~snxi`). When they are equal, `GetShortPathNameW` is a no-op, meaning 8.3 short names are disabled and the hook exits with actionable instructions. ### Motivation `GetShortPathNameW` is a no-op when 8.3 short names are disabled, causing Bazel to fail with an internal path-length error (bazelbuild/bazel#19710), even with the 260-character OS limit lifted. GitLab runners had the volume state enabled, but Docker containers did not, root cause of [#incident-56436](https://dd.enterprise.slack.com/archives/C0BBPAV0J20). The latter is now fixed by the combo: - DataDog/datadog-agent-buildimages#1215 - #52561. The present change makes it fail fast with actionable instructions rather than a cryptic Bazel error. ### Describe how you validated your changes Before #52561 was merged: https://gitlab.ddbuild.io/DataDog/datadog-agent/-/jobs/1788332180#L48 ### Additional Notes To be reverted once following upstream fix (or equivalent) is available: - bazelbuild/bazel#29921. Co-authored-by: regis.desgroppes <regis.desgroppes@datadoghq.com>
Collaborator
|
@bazel-io fork 9.2.0 |
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).