{"record":{"id":"eca7cab42dd9da6e","repo":"Yeachan-Heo/oh-my-codex","slug":"stderr-mission-dir-git-error","errorCode":null,"errorMessage":"${stderr || MISSION_DIR_GIT_ERROR}","messagePattern":"\\$\\{stderr \\|\\| MISSION_DIR_GIT_ERROR\\}","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/autoresearch/contracts.ts","lineNumber":63,"sourceCode":"  return new Error(message);\n}\n\nfunction readGit(repoPath: string, args: string[]): string {\n  try {\n    return execFileSync('git', args, {\n      cwd: repoPath,\n      encoding: 'utf-8',\n      stdio: ['ignore', 'pipe', 'pipe'],\n      windowsHide: true,\n    }).trim();\n  } catch (error) {\n    const err = error as NodeJS.ErrnoException & { stderr?: string | Buffer };\n    const stderr = typeof err.stderr === 'string'\n      ? err.stderr.trim()\n      : err.stderr instanceof Buffer\n        ? err.stderr.toString('utf-8').trim()\n        : '';\n    throw contractError(stderr || MISSION_DIR_GIT_ERROR);\n  }\n}\n\nexport function slugifyMissionName(value: string): string {\n  return value\n    .toLowerCase()\n    .replace(/[^a-z0-9]+/g, '-')\n    .replace(/-+/g, '-')\n    .replace(/^-|-$/g, '')\n    .slice(0, 48) || 'mission';\n}\n\nfunction ensurePathInside(parentPath: string, childPath: string): void {\n  const rel = relative(parentPath, childPath);\n  if (rel === '' || (!rel.startsWith('..') && rel !== '..')) return;\n  throw contractError(MISSION_DIR_GIT_ERROR);\n}\n","sourceCodeStart":45,"sourceCodeEnd":81,"githubUrl":"https://github.com/Yeachan-Heo/oh-my-codex/blob/3ad79a8a6fe6e95fdbb8c00e40716fffe4011ce2/src/autoresearch/contracts.ts#L45-L81","documentation":"Thrown by readGit in src/autoresearch/contracts.ts when a git subprocess it runs (e.g. git rev-parse --show-toplevel) fails. The error message is the trimmed stderr from git if available, otherwise the generic MISSION_DIR_GIT_ERROR message. This surfaces git invocation failures such as not being inside a repository or git not being installed.","triggerScenarios":"loadAutoresearchMissionContract -> readGit(missionDir, ['rev-parse','--show-toplevel']) when the mission directory is not inside a git work tree, git is not on PATH, or git exits non-zero for another reason (permissions, corrupt repo).","commonSituations":"Pointing --mission-dir at a plain folder that was never git-inited; running in a container/CI image without git; a .git directory with broken ownership ('dubious ownership' safe.directory errors).","solutions":["Verify the mission directory is inside a git repository: run git rev-parse --show-toplevel in it.","If git is missing, install git or ensure it is on PATH for the process.","If git printed stderr (e.g. 'detected dubious ownership'), fix accordingly — e.g. git config --global --add safe.directory <path>.","Initialize a repo (git init) if the mission folder was meant to be standalone."],"exampleFix":"// before\nconst contract = await loadAutoresearchMissionContract('/plain/folder/mission');\n\n// after\nawait exec('git -C /plain/folder init'); // or move mission inside an existing repo\nconst contract = await loadAutoresearchMissionContract('/plain/folder/mission');","handlingStrategy":"try-catch","validationCode":"import { execFile } from 'node:child_process';\nimport { promisify } from 'node:util';\nconst execFileAsync = promisify(execFile);\n\nasync function assertGitRepoAvailable(dir: string): Promise<void> {\n  await execFileAsync('git', ['-C', dir, 'rev-parse', '--show-toplevel'], { timeout: 5000 });\n}","typeGuard":null,"tryCatchPattern":"try {\n  const contract = await loadAutoresearchMissionContract(missionDir);\n} catch (err) {\n  const msg = err instanceof Error ? err.message : String(err);\n  if (msg.includes('git') || msg === MISSION_DIR_GIT_ERROR) {\n    // surface git stderr, suggest git init / PATH / safe.directory fixes\n  }\n  throw err;\n}","preventionTips":["Run 'git rev-parse --show-toplevel' in the mission dir as a preflight.","Ensure git is installed and on PATH in CI images.","Configure safe.directory for mounted/shared repos."],"tags":["git","subprocess","mission-dir","autoresearch"],"backgroundTag":"git-command-failed","analyzedSha":"3ad79a8a6fe6e95fdbb8c00e40716fffe4011ce2","analyzedAt":"2026-08-27T22:18:39.783Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}