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

Unsafe Autopilot context snapshot path: ${existingSnapshot.p

Error message

Unsafe Autopilot context snapshot path: ${existingSnapshot.path}

What it means

Thrown by ensureAutopilotContextSnapshot when an existing snapshot record is found but its path fails the isSafeAutopilotContextSnapshotPath check (e.g. absolute path, traversal, or outside the expected context directory). The hook validates legacy/prior snapshot paths before reusing them and refuses unsafe ones.

Source

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

  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}`);
  }

  if (options.allowTaskSnapshotCreation === false) {
    const slug = 'autopilot-recovery';
    const continuationInput = activationText.trim() || '<empty>';
    const reason = options.recoveryReason ?? 'missing-or-unsafe-legacy-context-snapshot';
    const body = [
      '# Autopilot context recovery',
      '',
      '- recovery status: degraded',
      `- recovery reason: ${reason}`,
      `- reason detail: ${AUTOPILOT_CONTEXT_RECOVERY_REASON_MESSAGES[reason]}`,
      `- continuation input: ${continuationInput}`,
      '- original task status: unavailable',
      '- original task seed: unavailable; do not treat the continuation input as the task seed.',
      '- required follow-up: re-establish or confirm the intended task context before downstream handoff.',
      '',
    ].join('\n');

View on GitHub (pinned to 3ad79a8a6f)

Solutions

  1. Delete or reset the stale snapshot record (and its file) under .omx/context so a fresh, safely-pathed snapshot is created
  2. Regenerate the snapshot index from scratch if it's a metadata file (back it up first)
  3. If you need the old snapshot, copy its contents into a new run rather than reusing the unsafe path
  4. Check the isSafeAutopilotContextSnapshotPath requirements and ensure your storage layer writes relative paths under .omx/context

Example fix

# before
# existing snapshot metadata has path '/abs/old/repo/.omx/context/snap.json'
run-hook  # throws

# after
rm -rf .omx/context  # or remove just the offending snapshot record
run-hook  # creates a fresh snapshot with a safe relative path
Defensive patterns

Strategy: try-catch

Validate before calling

import { isAbsolute, relative } from 'node:path';

function snapshotPathIsSafe(contextDir: string, p: unknown): p is string {
  if (typeof p !== 'string' || !p.trim() || isAbsolute(p)) return false;
  const rel = relative(contextDir, join(contextDir, p));
  return rel !== '' && !rel.startsWith('..') && !isAbsolute(rel);
}

Type guard

function isSafeSnapshotRecord(r: { path: unknown }): boolean {
  return typeof r.path === 'string' && !r.path.startsWith('/') && !r.path.includes('..');
}

Try / catch

try { snap = await ensureAutopilotContextSnapshot(cwd, iso, text); }
catch (err) {
  if ((err as Error).message.includes('Unsafe Autopilot context snapshot path')) {
    await resetContextSnapshots(cwd); // remove stale snapshot index/records
    snap = await ensureAutopilotContextSnapshot(cwd, iso, text);
  } else throw err;
}

Prevention

When it happens

Trigger: A prior run recorded a snapshot whose path is absolute, contains '..', points outside .omx/context, or was written by an older layout the safety check doesn't recognize; the detector then refuses to reuse it and throws before falling back to creation.

Common situations: Upgrading the hook to a version with stricter path validation while old snapshot metadata contains absolute or legacy-relative paths; manually edited/corrupted snapshot index files; snapshots recorded when the repo lived at a different path; partial migrations leaving mismatched path formats.

Related errors


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