authorgravatar for 38929917+raulpesilva@users.noreply.github.comRaul Pereira da Silva <38929917+raulpesilva@users.noreply.github.com> 2026-04-23 01:42:19-03:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2026-04-23 04:42:19+00:00
logb0b7b38da1dc4b19833d13f84eb907b1e2adfb63
tree121145229de1ac152b0473fbcd055349ad9c1af5
parentfd3b96b487a9aac8a011c27f977067d63d942ac1
signature Signed by PGP key B5690EEEBB952194

fix(server): detect localized Windows command errors (#2152)

Co-authored-by: macroscopeapp[bot] <170038800+macroscopeapp[bot]@users.noreply.github.com>

2 files changed, 33 insertions(+), 2 deletions(-)

apps/server/src/processRunner.test.ts+19-1
......@@ -1,6 +1,6 @@
11import { describe, expect, it } from "vitest";
22
3import { runProcess } from "./processRunner.ts";
3import { isWindowsCommandNotFound, runProcess } from "./processRunner.ts";
44
55describe("runProcess", () => {
66 it("fails when output exceeds max buffer in default mode", async () => {
......@@ -21,3 +21,21 @@ describe("runProcess", () => {
2121 expect(result.stderrTruncated).toBe(false);
2222 });
2323});
24
25describe("isWindowsCommandNotFound", () => {
26 it("matches the localized German cmd.exe error text", () => {
27 const originalPlatform = process.platform;
28 Object.defineProperty(process, "platform", { value: "win32", configurable: true });
29
30 try {
31 expect(
32 isWindowsCommandNotFound(
33 1,
34 "wird nicht als interner oder externer Befehl, betriebsfahiges Programm oder Batch-Datei erkannt",
35 ),
36 ).toBe(true);
37 } finally {
38 Object.defineProperty(process, "platform", { value: originalPlatform, configurable: true });
39 }
40 });
41});
apps/server/src/processRunner.ts+14-1
......@@ -37,10 +37,23 @@ function normalizeSpawnError(command: string, args: readonly string[], error: un
3737 return new Error(`Failed to run ${commandLabel(command, args)}: ${error.message}`);
3838}
3939
40const WINDOWS_COMMAND_NOT_FOUND_PATTERNS = [
41 /is not recognized as an internal or external command/i,
42 /n.o . reconhecido como um comando interno/i,
43 /non . riconosciuto come comando interno o esterno/i,
44 /n.est pas reconnu en tant que commande interne/i,
45 /no se reconoce como un comando interno o externo/i,
46 /wird nicht als interner oder externer befehl/i,
47] as const;
48
49function hasWindowsCommandNotFoundMessage(output: string): boolean {
50 return WINDOWS_COMMAND_NOT_FOUND_PATTERNS.some((pattern) => pattern.test(output));
51}
52
4053export function isWindowsCommandNotFound(code: number | null, stderr: string): boolean {
4154 if (process.platform !== "win32") return false;
4255 if (code === 9009) return true;
43 return /is not recognized as an internal or external command/i.test(stderr);
56 return hasWindowsCommandNotFoundMessage(stderr);
4457}
4558
4659function normalizeExitError(