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

Unable to allocate unique Autopilot context snapshot for ${s

Error message

Unable to allocate unique Autopilot context snapshot for ${slug}

What it means

Thrown by writeUniqueAutopilotContextSnapshot when it exhausts its allocation attempts: it tries to create snapshot files with an exclusive (O_EXCL-style) create, and on every attempt the candidate filename already exists (EEXIST), eventually exceeding the retry budget for the given slug. Non-EEXIST errors propagate immediately.

Source

Thrown at src/hooks/keyword-detector.ts:403

  nowIso: string,
  body: string,
): Promise<string> {
  const contextDir = await ensureSafeAutopilotContextDir(sourceCwd);
  const timestamp = utcCompactTimestamp(nowIso);
  for (let attempt = 0; attempt < 100; attempt += 1) {
    const suffix = attempt === 0 ? '' : `-${attempt + 1}`;
    const filename = `${slug}-${timestamp}${suffix}.md`;
    const relativePath = `.omx/context/${filename}`;
    const absolutePath = resolve(contextDir, filename);
    try {
      await writeFile(absolutePath, body, { encoding: 'utf-8', flag: 'wx' });
      return relativePath;
    } catch (error) {
      if ((error as NodeJS.ErrnoException).code === 'EEXIST') continue;
      throw error;
    }
  }
  throw new Error(`Unable to allocate unique Autopilot context snapshot for ${slug}`);
}

async function ensureAutopilotContextSnapshot(
  sourceCwd: string,
  nowIso: string,
  activationText: string,
  existingSnapshot?: AutopilotContextSnapshotDescriptor,
  options: { allowTaskSnapshotCreation?: boolean; recoveryReason?: AutopilotContextRecoveryReason } = {},
): Promise<AutopilotContextSnapshotResult> {
  if (existingSnapshot) {
    if (isSafeAutopilotContextSnapshotPath(existingSnapshot.path)) {
      return {
        path: existingSnapshot.path,
        kind: existingSnapshot.kind,
        original_task_status: existingSnapshot.kind === 'legacy' ? 'legacy-unverified' : 'activation-prompt',
      };
    }
    throw new Error(`Unsafe Autopilot context snapshot path: ${existingSnapshot.path}`);

View on GitHub (pinned to 3ad79a8a6f)

Solutions

  1. Reduce parallelism or stagger invocations so timestamps differ (pass distinct nowIso values per invocation)
  2. Clean up old snapshot files for the slug under .omx/context if they're stale/disposable
  3. Pass a more unique slug per invocation so candidate names don't collide
  4. Report upstream if legitimate sequential usage exhausts the attempt budget — the retry count may need increasing

Example fix

// before
for (const item of items) await ensureAutopilotContextSnapshot(cwd, sameIso, item.slug); // same slug+time repeatedly

// after
for (const item of items) {
  await ensureAutopilotContextSnapshot(cwd, new Date().toISOString(), `${item.slug}-${crypto.randomUUID().slice(0,6)}`);
}
Defensive patterns

Strategy: retry

Validate before calling

import { access } from 'node:fs/promises';

async function snapshotNameLikelyFree(dir: string, slug: string, iso: string): Promise<boolean> {
  const base = `${slug}-${iso.replace(/[-:]/g, '').replace(/\.\d{3}Z$/, 'Z')}`;
  try { await access(join(dir, base + '.json')); return false; } catch { return true; }
}

Try / catch

for (let i = 0; i < 3; i++) {
  try { return await ensureAutopilotContextSnapshot(cwd, new Date().toISOString(), slug); }
  catch (err) {
    if (!(err as Error).message.includes('Unable to allocate unique Autopilot context snapshot')) throw err;
    slug = `${slug}-${crypto.randomUUID().slice(0, 6)}`;
  }
}
throw new Error('snapshot allocation failed');

Prevention

When it happens

Trigger: Many snapshots created within the same timestamp window for the same slug (e.g. a loop or fan-out invoking the hook dozens of times in the same second), so all candidate suffixed filenames are taken; or a hostile/pre-existing set of files squatting every candidate name for that slug.

Common situations: Parallel test suites triggering the hook hundreds of times; automation retry storms re-invoking the detector with the same slug and timestamp; clock skew making 'now' identical across many invocations; leftover snapshot files filling the namespace.

Related errors


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