{"record":{"id":"074305a389595c3e","repo":"jarrodwatts/claude-hud","slug":"unable-to-resolve-an-absolute-git-exe-from-path","errorCode":null,"errorMessage":"Unable to resolve an absolute git.exe from PATH","messagePattern":"Unable to resolve an absolute git\\.exe from PATH","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"critical","filePath":"src/git-runner.ts","lineNumber":92,"sourceCode":"    return { stdout };\n  }\n\n  async close(): Promise<void> {\n    // Direct commands have no session process to release.\n  }\n}\n\nclass WindowsGitRunner implements GitCommandRunner {\n  private readonly worker: ChildProcess;\n  private nextId = 1;\n  private pending: PendingCommand | null = null;\n  private exited = false;\n  private closing = false;\n\n  constructor(private readonly cwd: string) {\n    const workerPath = fileURLToPath(new URL('./windows-git-worker.js', import.meta.url));\n    const gitExecutable = resolveWindowsGitExecutable();\n    if (!gitExecutable) throw new Error('Unable to resolve an absolute git.exe from PATH');\n\n    this.worker = spawn(process.execPath, [workerPath, gitExecutable], {\n      env: createGitEnvironment(),\n      windowsHide: true,\n      shell: false,\n      stdio: ['ignore', 'ignore', 'ignore', 'ipc'],\n    });\n\n    this.worker.on('message', (message: unknown) => this.handleMessage(message));\n    this.worker.once('error', (error) => this.failPending(error));\n    this.worker.once('exit', (code, signal) => {\n      this.exited = true;\n      if (!this.closing) {\n        this.failPending(new Error(`Git worker exited unexpectedly (${signal ?? code ?? 'unknown'})`));\n      }\n    });\n  }\n","sourceCodeStart":74,"sourceCodeEnd":110,"githubUrl":"https://github.com/jarrodwatts/claude-hud/blob/939eb66485832dead1b0a28a954f76f7aa2bdb06/src/git-runner.ts#L74-L110","documentation":"On Windows, WindowsGitRunner spawns a detached worker process with shell:false and an absolute path to git.exe, so it never relies on PATH lookup at spawn time. During construction it calls resolveWindowsGitExecutable(), which scans every absolute entry of the PATH environment variable for a git.exe that exists and is a regular file (src/git-runner.ts:289-312). If no such entry is found, the constructor throws 'Unable to resolve an absolute git.exe from PATH' — the library refuses to run because the worker could not launch git.","triggerScenarios":"Constructing WindowsGitRunner (new WindowsGitRunner(cwd)) on Windows when resolveWindowsGitExecutable returns null: (1) PATH env var is unset or empty; (2) PATH contains only relative entries (entries that are not path.win32.isAbsolute are skipped); (3) no PATH entry contains git.exe, or the git.exe candidate fails statSync/isFile (e.g. Git not installed, or only git.cmd/git-wrapper present); (4) PATH entries contain embedded NUL characters or fail realpathSync.","commonSituations":"Git for Windows not installed or installed in a non-PATH location (e.g. portable Git); running under a service/CI account whose PATH lacks the usual 'C:\\Program Files\\Git\\cmd'; PATH stripped or overridden by a sanitized environment (spawn env customization, containers, GUI-launched apps inheriting minimal PATH); Git exposed only as git.exe via a shell alias or via git.cmd in cmd/ with an older layout where git.exe sits elsewhere; corrupted PATH with quoted or malformed entries.","solutions":["Install Git for Windows (or point PATH at an existing install's cmd directory, e.g. C:\\Program Files\\Git\\cmd) and restart the shell/process so PATH is picked up.","Verify with 'where git.exe' in cmd (or 'Get-Command git.exe' in PowerShell) that git.exe resolves via an absolute PATH entry; fix PATH ordering/entries if not.","If PATH is intentionally sanitized, set a PATH environment variable containing the absolute directory of git.exe before constructing the runner.","Use a machine where git.exe exists on disk at an absolute path; relative PATH directories are deliberately ignored by the resolver for security (repo-controlled lookups).","As a last resort, patch/extend the environment passed to the runner so PATH includes the Git cmd directory (createGitEnvironment preserves PATH-based resolution)."],"exampleFix":"// before (no git.exe reachable from PATH)\nconst runner = new WindowsGitRunner(repoCwd); // throws\n\n// after (ensure PATH includes Git before constructing)\nprocess.env.PATH = ['C:\\\\Program Files\\\\Git\\\\cmd', process.env.PATH].join(path.win32.delimiter);\nconst runner = new WindowsGitRunner(repoCwd);","handlingStrategy":"try-catch","validationCode":"import { resolveWindowsGitExecutable } from './src/git-runner.js';\n\nfunction canConstructWindowsGitRunner(): boolean {\n  return resolveWindowsGitExecutable() !== null;\n}\n\nif (!canConstructWindowsGitRunner()) {\n  // fix PATH / install Git before proceeding\n}","typeGuard":"function hasGitExecutable(\n  resolveCandidate: (c: string) => string | null = (c) => {\n    try { const r = require('fs').realpathSync(c); return require('fs').statSync(r).isFile() ? r : null; } catch { return null; }\n  },\n): boolean {\n  return resolveWindowsGitExecutable(process.env, resolveCandidate) !== null;\n}","tryCatchPattern":"let runner: WindowsGitRunner;\ntry {\n  runner = new WindowsGitRunner(cwd);\n} catch (err) {\n  if (err instanceof Error && err.message.includes('Unable to resolve an absolute git.exe')) {\n    // fall back: report missing Git, or use a different runner / disable git features\n    throw new Error('Git for Windows not found on PATH; install it or fix PATH.', { cause: err });\n  }\n  throw err;\n}","preventionTips":["In installation/setup docs, require Git for Windows and verify 'where git.exe' resolves during bootstrap.","Check resolveWindowsGitExecutable() at app startup and surface a clear setup error before any runner construction.","Never sanitize PATH to only relative directories when spawning tooling; always keep absolute Git cmd directory entries.","In CI/service contexts, explicitly set PATH to include the Git installation directory rather than relying on inherited environment.","Prefer absolute Git paths passed via environment/config over relying on PATH lookup."],"tags":["windows","git","path-resolution","environment","constructor-throw"],"backgroundTag":"git-executable-not-found","analyzedSha":"939eb66485832dead1b0a28a954f76f7aa2bdb06","analyzedAt":"2026-08-29T09:24:37.988Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}