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
- Delete or reset the stale snapshot record (and its file) under .omx/context so a fresh, safely-pathed snapshot is created
- Regenerate the snapshot index from scratch if it's a metadata file (back it up first)
- If you need the old snapshot, copy its contents into a new run rather than reusing the unsafe path
- 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
- Store snapshot paths as relative paths under .omx/context from day one
- Reset snapshot metadata after major version upgrades of the hook
- Validate persisted paths against the context dir on load, not just on reuse
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
- worktreeName must be a relative safe worktree name
- Blocked ultragoal checkpoint Codex snapshot is missing objec
- invalid auth slot path
- Autoresearch goal ${mission.slug} cannot complete until prof
- formatCodexGoalReconciliation(reconciliation)
AI-assisted analysis of Yeachan-Heo/oh-my-codex@3ad79a8a6f (2026-08-27).
Data as JSON: /api/errors/e3f4349c025c72e3.
Report an issue: GitHub.