What happened?
Every Windows job of the PR validation workflow (Build / FiveM, Build / RedM, Build / Server) fails before a single translation unit is compiled.
.github/workflows/ci/build_windows.sh invokes MSBuild through a hardcoded path:
"C:\Program Files\Microsoft Visual Studio\2022\Enterprise\MSBuild\Current\Bin\MsBuild.exe" CitizenMP.sln ...
ci_build.yml runs these jobs on runs-on: windows-latest, and that label now resolves to the windows-2025-vs2026 runner image (Visual Studio 2026), so the VS 2022 path no longer exists:
.github/workflows/ci/build_windows.sh: line 8: C:\Program Files\Microsoft Visual Studio\2022\Enterprise\MSBuild\Current\Bin\MsBuild.exe: No such file or directory
.github/workflows/ci/build_windows.sh: line 20: errors.log: No such file or directory
##[error]Failed to build rdr3, MSBuild returned with error code: 127
Exit code 127 is the shell's "command not found", so the failure happens before MSBuild runs. Project generation itself succeeds — the log shows Generated build/rdr3/*.vcxproj ... Done (14369ms) immediately before the error — because code/tools/fxd/gen.ps1 already locates Visual Studio dynamically with the bundled code/tools/ci/vswhere.exe. Only the MSBuild invocation is hardcoded.
Runner image reported in the logs:
Image: windows-2025-vs2026
Version: 20260824.214.3
Expected result
Windows build jobs locate MSBuild on the runner and compile, so PR validation reflects the state of the code under review.
Reproduction steps
- Open a pull request touching any path that requires compilation (anything under
code/, or an ext/native-decls/*.md file).
- Wait for the
Validate PR workflow to reach Build / FiveM, Build / RedM and Build / Server.
- Every Windows job fails in the
Compile step with exit code 127.
Scope
This is not specific to one PR. Across the last 100 Validate PR runs (2026-08-06 → 2026-09-07), no Windows build has succeeded. The only runs reporting success are those where input_validation determined no compilation was required and the Build job was skipped.
Because post_build applies the invalid label whenever any needed job fails, every PR that touches a compiled path is currently labelled invalid regardless of its contents.
Examples: 34147689136, 34103382485, 33561136821.
Area(s)
FiveM, RedM, FXServer — CI only, no runtime impact.
Specific version(s)
master @ 0d8a2a6, and every run in the window above.
Additional information
Two possible directions, both one-liners:
-
Resolve MSBuild with the vswhere binary already vendored in this repo, mirroring what gen.ps1 does, so the script stops caring which VS version the image ships:
MSBUILD=$(./code/tools/ci/vswhere.exe -prerelease -latest -products '*' \
-requires Microsoft.Component.MSBuild \
-find 'MSBuild\**\Bin\MSBuild.exe' | head -1)
(resolved before the cd into code/build/..., then invoked as "$MSBUILD")
-
Pin the runner to windows-2022 in ci_build.yml, restoring the previous environment exactly.
Option 1 is the more durable fix, but it moves the build onto whatever toolset the image ships; I have no way to verify from outside whether this codebase compiles cleanly under the VS 2026 toolset with systemversion '10.0.22000.0'. Option 2 is guaranteed to restore the previously working environment but will need revisiting when that image is retired. Happy to open a PR for whichever you prefer.
What happened?
Every Windows job of the PR validation workflow (
Build / FiveM,Build / RedM,Build / Server) fails before a single translation unit is compiled..github/workflows/ci/build_windows.shinvokes MSBuild through a hardcoded path:"C:\Program Files\Microsoft Visual Studio\2022\Enterprise\MSBuild\Current\Bin\MsBuild.exe" CitizenMP.sln ...ci_build.ymlruns these jobs onruns-on: windows-latest, and that label now resolves to thewindows-2025-vs2026runner image (Visual Studio 2026), so the VS 2022 path no longer exists:Exit code 127 is the shell's "command not found", so the failure happens before MSBuild runs. Project generation itself succeeds — the log shows
Generated build/rdr3/*.vcxproj ... Done (14369ms)immediately before the error — becausecode/tools/fxd/gen.ps1already locates Visual Studio dynamically with the bundledcode/tools/ci/vswhere.exe. Only the MSBuild invocation is hardcoded.Runner image reported in the logs:
Expected result
Windows build jobs locate MSBuild on the runner and compile, so PR validation reflects the state of the code under review.
Reproduction steps
code/, or anext/native-decls/*.mdfile).Validate PRworkflow to reachBuild / FiveM,Build / RedMandBuild / Server.Compilestep with exit code 127.Scope
This is not specific to one PR. Across the last 100
Validate PRruns (2026-08-06 → 2026-09-07), no Windows build has succeeded. The only runs reporting success are those whereinput_validationdetermined no compilation was required and theBuildjob was skipped.Because
post_buildapplies theinvalidlabel whenever any needed job fails, every PR that touches a compiled path is currently labelledinvalidregardless of its contents.Examples: 34147689136, 34103382485, 33561136821.
Area(s)
FiveM, RedM, FXServer — CI only, no runtime impact.
Specific version(s)
master@ 0d8a2a6, and every run in the window above.Additional information
Two possible directions, both one-liners:
Resolve MSBuild with the vswhere binary already vendored in this repo, mirroring what
gen.ps1does, so the script stops caring which VS version the image ships:(resolved before the
cdintocode/build/..., then invoked as"$MSBUILD")Pin the runner to
windows-2022inci_build.yml, restoring the previous environment exactly.Option 1 is the more durable fix, but it moves the build onto whatever toolset the image ships; I have no way to verify from outside whether this codebase compiles cleanly under the VS 2026 toolset with
systemversion '10.0.22000.0'. Option 2 is guaranteed to restore the previously working environment but will need revisiting when that image is retired. Happy to open a PR for whichever you prefer.