{"record":{"id":"3035d60d83705d1c","repo":"ruvnet/ruflo","slug":"git-returned-a-non-nul-terminated-path-list","errorCode":null,"errorMessage":"Git returned a non-NUL-terminated path list","messagePattern":"Git returned a non-NUL-terminated path list","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"v3/@claude-flow/codex/src/harness/repository-state.ts","lineNumber":181,"sourceCode":"\nfunction optionalGitText(repoRoot: string, args: readonly string[]): string | undefined {\n  try {\n    const value = gitText(repoRoot, args);\n    return value.length > 0 ? value : undefined;\n  } catch {\n    return undefined;\n  }\n}\n\nfunction splitNul(output: Buffer): Buffer[] {\n  const records: Buffer[] = [];\n  let start = 0;\n  for (let index = 0; index < output.length; index += 1) {\n    if (output[index] !== 0) continue;\n    if (index > start) records.push(output.subarray(start, index));\n    start = index + 1;\n  }\n  if (start !== output.length) throw new Error('Git returned a non-NUL-terminated path list');\n  return records;\n}\n\nfunction decodeGitPath(bytes: Buffer): string {\n  const path = bytes.toString('utf8');\n  if (!Buffer.from(path, 'utf8').equals(bytes)) {\n    throw new Error('Git path is not valid round-trip UTF-8');\n  }\n  assertUnicodeScalarString(path);\n  if (path !== path.normalize('NFC')) {\n    throw new Error(`Git path is not NFC-normalized: ${path}`);\n  }\n  return normalizeRelativePath(path);\n}\n\nfunction normalizeRelativePath(path: string): string {\n  assertUnicodeScalarString(path);\n  if (path.includes('\\\\')) throw new Error(`ambiguous repository path separator: ${path}`);","sourceCodeStart":163,"sourceCodeEnd":199,"githubUrl":"https://github.com/ruvnet/ruflo/blob/fa13ee4ad60ac2090b1480656eb233521790d640/v3/@claude-flow/codex/src/harness/repository-state.ts#L163-L199","documentation":"splitNul parses stdout of git listing commands run with -z (git ls-files -z, ls-files --stage -z, and similar via execFileSync). Every record must be NUL-terminated; a trailing non-empty segment after the last NUL means the output does not conform to the -z contract — truncated, reformatted, or produced by something other than stock git. The check runs before paths are trusted for source-state digests.","triggerScenarios":"A 'git' shim earlier on PATH (wrapper scripts, node_modules/.bin, PATH routers) that reformats output or drops -z; stdout truncated mid-path; git aliases/hooks printing advice or progress to stdout; a git build whose ls-files output omits the final NUL.","commonSituations":"Corporate machines with git wrappers; environment PATH shims intercepting git; large repos where output streams get truncated; environments with aggressive git config (aliases, advice) inherited from dotfiles.","solutions":["Run `git --version` and `command -v git` from the same environment the harness runs in; remove any wrapper/shim so the real git binary is invoked","Reproduce manually: `git -C <repo> ls-files -z | od -c | tail -3` and confirm the output ends with \\\\0","Unset interfering git env/config for the harness process (GIT_ALIASES, advice, aliases defined in .gitconfig)","If stock git reproduces it, capture git version and a byte dump and report it to maintainers"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"import { execFileSync } from 'node:child_process';\nfunction preflightGitNulTermination(repoRoot: string): void {\n  const out = execFileSync('git', ['-C', repoRoot, 'ls-files', '-z'], { encoding: 'buffer', maxBuffer: 1024 * 1024 * 512 });\n  if (out.length > 0 && out[out.length - 1] !== 0) {\n    throw new Error(`git on PATH is not emitting NUL-terminated listings; check: ${execFileSync('which', ['git']).toString().trim()}`);\n  }\n}","typeGuard":null,"tryCatchPattern":"try {\n  const state = captureSourceState(repoRoot);\n} catch (error) {\n  if (error instanceof Error && error.message === 'Git returned a non-NUL-terminated path list') {\n    throw new Error(`git output malformed (PATH shim or truncated stdout?): git = ${process.env.PATH}`);\n  }\n  throw error;\n}","preventionTips":["Run `command -v git` and `git --version` in the harness environment; remove wrappers/shims from PATH","Do not pipe git output through text tools or aliases that strip NUL bytes","Keep git reasonably current and free of hooks/aliases that write to stdout"],"tags":["git","filesystem","process-output","repository-state"],"backgroundTag":"git-output-parse-error","analyzedSha":"fa13ee4ad60ac2090b1480656eb233521790d640","analyzedAt":"2026-08-18T21:34:22.708Z","contentChangedAt":"2026-08-18T21:34:22.708Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}