{"record":{"id":"cf0a184be0054697","repo":"ruvnet/ruflo","slug":"malformed-git-index-record","errorCode":null,"errorMessage":"malformed Git index record","messagePattern":"malformed Git index record","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"v3/@claude-flow/codex/src/harness/repository-state.ts","lineNumber":302,"sourceCode":"  return { digest: digest(canonicalJson(entries)), entries };\n}\n\nfunction trackedPatch(repoRoot: string): ContentDigest {\n  return contentDigest(gitBuffer(repoRoot, [\n    'diff',\n    '--binary',\n    '--full-index',\n    '--no-ext-diff',\n    'HEAD',\n    '--',\n  ]));\n}\n\nfunction submoduleStates(repoRoot: string): readonly SubmoduleState[] {\n  const staged = splitNul(gitBuffer(repoRoot, ['ls-files', '--stage', '-z']));\n  const submodules = staged.flatMap((entry): Array<{ path: string; commit: string }> => {\n    const tab = entry.indexOf(0x09);\n    if (tab < 0) throw new Error('malformed Git index record');\n    const metadata = entry.subarray(0, tab).toString('ascii');\n    const match = /^160000 ([0-9a-f]+) [0-3]$/.exec(metadata);\n    return match?.[1]\n      ? [{ path: decodeGitPath(entry.subarray(tab + 1)), commit: match[1] }]\n      : [];\n  });\n  assertNoPathCollisions(submodules.map(({ path }) => path));\n\n  return submodules.map(({ path, commit }): SubmoduleState => {\n    const absolute = resolve(repoRoot, path);\n    assertInsideRepository(repoRoot, absolute);\n    const actualCommit = optionalGitText(absolute, ['rev-parse', '--verify', 'HEAD']);\n    if (!actualCommit) {\n      return {\n        path,\n        initialized: false,\n        expectedCommit: commit,\n        trackedPatch: contentDigest(Buffer.alloc(0)),","sourceCodeStart":284,"sourceCodeEnd":320,"githubUrl":"https://github.com/ruvnet/ruflo/blob/fa13ee4ad60ac2090b1480656eb233521790d640/v3/@claude-flow/codex/src/harness/repository-state.ts#L284-L320","documentation":"submoduleStates() parses the output of `git ls-files --stage -z`; each record must contain a tab (0x09) separating '<mode> <sha> <stage>' metadata from the path. A record with no tab means the output does not match the expected git format, so parsing aborts with 'malformed Git index record'.","triggerScenarios":"A git version or wrapper that emits `ls-files --stage` output in a different shape; a corrupted index producing garbage records; output mangled by GIT_EXTERNAL_DIFF/aliases or a shim in front of git.","commonSituations":"Very old or exotic git builds, git installed via wrappers (hub, containers, busybox git), or a .git/index corrupted by a crash — the regex/tab contract silently breaks.","solutions":["Run `git ls-files --stage` manually and inspect the raw output for records without a tab","Rebuild the index: `rm .git/index && git reset`","Upgrade git to a current stable release and remove any git shims/aliases from PATH"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"const records = execFileSync('git', ['-C', root, 'ls-files', '--stage', '-z']);\nfor (const rec of splitNul(records)) if (!rec.includes(0x09)) throw new Error('unexpected git output shape');","typeGuard":null,"tryCatchPattern":"try { capture(); } catch (e) { if (/malformed Git index record/.test(String(e))) { rebuildIndexOrUpgradeGit(); } throw e; }","preventionTips":["Pin a current stable git version in CI and devcontainers","Avoid git shims/wrappers that rewrite plumbing output","Run git fsck after crashes"],"tags":["git","parsing","index-corruption","version-compat"],"backgroundTag":"git-output-parse-failure","analyzedSha":"fa13ee4ad60ac2090b1480656eb233521790d640","analyzedAt":"2026-08-18T21:34:22.708Z","schemaVersion":2},"datasetVersion":"2026-08-22T14:17:55.899Z"}