Yeachan-Heo/oh-my-codex · error · Error

autoresearch_worktree_requires_named_mode

autoresearch_worktree_requires_named_mode

Error message

autoresearch_worktree_requires_named_mode

What it means

Thrown when planning an autoresearch-scoped worktree path while the mode is disabled or detached. Autoresearch worktrees are named after the mode (`autoresearch-<mode>-<runTag>`), so a named, attached mode is mandatory in that scope.

Source

Thrown at src/team/worktree.ts:236

  }

  return `${input.mode.name}/${workerName}`;
}

function resolveWorktreePath(input: WorktreePlanInput, repoRoot: string): string {
  const parent = dirname(repoRoot);
  const bucket = `${basename(repoRoot)}.omx-worktrees`;

  if (input.scope === 'launch') {
    if (!input.mode.enabled || input.mode.detached) {
      return join(parent, bucket, 'launch-detached');
    }
    return join(parent, bucket, `launch-${sanitizePathToken(input.mode.name)}`);
  }

  if (input.scope === 'autoresearch') {
    if (!input.mode.enabled || input.mode.detached) {
      throw new Error('autoresearch_worktree_requires_named_mode');
    }
    const runTag = sanitizePathToken(input.worktreeTag || 'run');
    return join(repoRoot, '.omx', 'worktrees', `autoresearch-${sanitizePathToken(input.mode.name)}-${runTag}`);
  }

  const teamName = sanitizePathToken(input.teamName || 'team');
  const workerName = sanitizePathToken(input.workerName || 'worker');
  return join(repoRoot, '.omx', 'team', teamName, 'worktrees', workerName);
}

function findWorktreeByPath(entries: GitWorktreeEntry[], worktreePath: string): GitWorktreeEntry | null {
  const resolved = resolve(worktreePath);
  return entries.find((entry) => resolve(entry.path) === resolved) || null;
}

function hasBranchInUse(entries: GitWorktreeEntry[], branchName: string, worktreePath: string): boolean {
  const expectedRef = `refs/heads/${branchName}`;
  const resolvedPath = resolve(worktreePath);

View on GitHub (pinned to 3ad79a8a6f)

Solutions

  1. Set mode = { enabled: true, detached: false, name: <non-empty> } when scope is 'autoresearch'
  2. Audit the code that builds WorktreePlanInput and assert the scope/mode invariants before calling the planner
  3. If you actually want a detached worktree, use a scope that supports it (team/launch path) instead of 'autoresearch'

Example fix

// before
planWorktreeTarget({ scope: 'autoresearch', mode: { enabled: false, name: 'eval' }, ... });

// after
planWorktreeTarget({ scope: 'autoresearch', mode: { enabled: true, detached: false, name: 'eval' }, ... });
Defensive patterns

Strategy: validation

Validate before calling

function isValidAutoresearchMode(mode: { enabled?: boolean; detached?: boolean; name?: string }): boolean {
  return mode.enabled === true && mode.detached !== true && !!mode.name?.trim();
}

Type guard

function isNamedAttachedMode(m: unknown): m is { enabled: true; detached: false; name: string } {
  return !!m && typeof m === 'object' && (m as any).enabled === true && (m as any).detached !== true && typeof (m as any).name === 'string' && (m as any).name.length > 0;
}

Try / catch

catch (e) { if (e instanceof Error && e.message === 'autoresearch_worktree_requires_named_mode') { /* fix mode config or switch scope */ } else throw e; }

Prevention

When it happens

Trigger: Calling planWorktreeTarget with scope 'autoresearch' and mode.enabled false, or mode.enabled true with mode.detached true.

Common situations: Config built dynamically where the mode block ends up `{ enabled: false, name: 'x' }` for autoresearch scope; reusing a detached-mode config for the autoresearch scope; typos in mode flags causing detached to default true.

Related errors


AI-assisted analysis of Yeachan-Heo/oh-my-codex@3ad79a8a6f (2026-08-27). Data as JSON: /api/errors/3486f426b9a46d15. Report an issue: GitHub.