Yeachan-Heo/oh-my-codex · error · Error
leader_workspace_dirty_for_worktrees
leader_workspace_dirty_for_worktrees
Error message
leader_workspace_dirty_for_worktrees:${resolve(cwd)}:${preview}:commit_or_stash_before_omx_team What it means
Thrown by assertCleanLeaderWorkspaceForWorkerWorktrees before starting team workers: the leader workspace (cwd) has uncommitted or untracked files, shown as a preview of the first 8 status lines. The library requires a clean leader workspace so worker worktrees branch off a reproducible commit.
Source
Thrown at src/team/worktree.ts:156
cwd,
encoding: 'utf-8',
windowsHide: true,
});
if (result.status !== 0) {
const stderr = (result.stderr || '').trim();
throw new Error(stderr || `workspace_status_failed:${cwd}`);
}
return (result.stdout || '')
.split(/\r?\n/)
.map((line) => line.trimEnd())
.filter(Boolean);
}
export function assertCleanLeaderWorkspaceForWorkerWorktrees(cwd: string): void {
const lines = readWorkspaceStatusLines(cwd);
if (lines.length === 0) return;
const preview = lines.slice(0, 8).join(' | ');
throw new Error(
`leader_workspace_dirty_for_worktrees:${resolve(cwd)}:${preview}:commit_or_stash_before_omx_team`,
);
}
function listWorktrees(repoRoot: string): GitWorktreeEntry[] {
const raw = readGit(repoRoot, ['worktree', 'list', '--porcelain']);
if (!raw) return [];
const entries: GitWorktreeEntry[] = [];
const chunks = raw
.split(/\n\n+/)
.map((chunk) => chunk.trim())
.filter(Boolean);
for (const chunk of chunks) {
const lines = chunk
.split(/\r?\n/)
.map((line) => line.trim())View on GitHub (pinned to 3ad79a8a6f)
Solutions
- Commit or stash all changes including untracked files: `git add -A && git commit` or `git stash --include-untracked`
- Add build outputs and logs to .gitignore so untracked artifacts stop blocking the check
- If the changes are disposable, clean them: `git checkout -- . && git clean -fd` (verify nothing valuable will be lost)
- Make your pipeline run the clean check itself before invoking startTeam and surface a friendly message
Example fix
# before: dirty workspace blocks startTeam git status --porcelain # shows M src/x.ts, ?? dist/ # after git add -A && git commit -m "wip before team run" # or: git stash --include-untracked printf 'dist/\n*.log\n' >> .gitignore
Defensive patterns
Strategy: validation
Validate before calling
import { readWorkspaceStatusLines } from './worktree';
function assertClean(cwd: string): void {
const lines = readWorkspaceStatusLines(cwd);
if (lines.length > 0) {
throw new Error(`Refusing to start: ${lines.length} uncommitted changes. Commit or stash first.`);
}
} Try / catch
try { startTeam(...); } catch (e) { if (String(e?.message).startsWith('leader_workspace_dirty_for_worktrees')) { const [path, preview] = e.message.split(':').slice(1); /* show preview to user, suggest git stash --include-untracked */ } else throw e; } Prevention
- Run `git status --porcelain --untracked-files=all` yourself before startTeam and act on it
- Keep a comprehensive .gitignore for build outputs and logs
- Adopt the habit of committing or stashing before long-running team commands
When it happens
Trigger: Calling startTeam (or the assert directly) while `git status --porcelain --untracked-files=all` in cwd returns any lines — modified files, staged changes, untracked files, or untracked build artifacts all count.
Common situations: Running the team command after building locally (dist/, node_modules/ not gitignored); forgetting to commit generated config edits; untracked log files; CI leaving artifacts in the tree; merging/rebasing left unresolved state.
Related errors
- worktree_not_planned:${workerName}
- worktree_not_provisioned:${workerName}
- (result.stderr || '').trim() || `git ${args.join(' ')} faile
- (result.stderr || '').trim() || `git status failed for ${wor
- autoresearch_reset_requires_clean_worktree
AI-assisted analysis of Yeachan-Heo/oh-my-codex@3ad79a8a6f (2026-08-27).
Data as JSON: /api/errors/d97fb398fc7b0173.
Report an issue: GitHub.