Yeachan-Heo/oh-my-codex · error · Error
Refusing cancellation through non-regular state target ${ref
Error message
Refusing cancellation through non-regular state target ${ref.path}. What it means
Before touching state files, the cancel command lstats each referenced path and requires it to be a regular file that is not a symbolic link. If the target is a symlink, directory, fifo, or missing/special file, cancellation refuses to proceed. This blocks attacks and accidents where state paths are redirected via links.
Source
Thrown at src/cli/index.ts:8407
string,
{
path: string;
scope: "root" | "session";
state: Record<string, unknown>;
originalContent: string;
dev: number;
ino: number;
}
>();
if (refs.length === 0) return loaded;
const canonicalAuthorityRoot = assertCancellationAuthorityPath(
authorityRoot === writableScope.stateDir ? baseStateDir : authorityRoot,
authorityRoot,
);
for (const ref of refs) {
const fileStat = lstatSync(ref.path);
if (!fileStat.isFile() || fileStat.isSymbolicLink()) {
throw new Error(`Refusing cancellation through non-regular state target ${ref.path}.`);
}
const canonicalPath = realpathSync(ref.path);
const canonicalParent = realpathSync(dirname(ref.path));
if (!isCanonicalPathWithin(canonicalAuthorityRoot, canonicalParent, true)
|| !isCanonicalPathWithin(canonicalAuthorityRoot, canonicalPath)) {
throw new Error(`Refusing cancellation outside authorized state root: ${ref.path}.`);
}
const content = await readFile(canonicalPath, "utf-8");
let parsedState: Record<string, unknown>;
try {
const parsed = JSON.parse(content) as unknown;
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
throw new Error("state must be a JSON object");
}
parsedState = parsed as Record<string, unknown>;
} catch (err) {
logCliOperationFailure(err);
throw new Error(`Refusing partial cancellation because ${ref.path} is malformed.`, { cause: err });View on GitHub (pinned to 3ad79a8a6f)
Solutions
- Replace the symlink at the referenced path with a real regular file (copy contents, remove link)
- Point configuration at the actual state directory instead of linking into it
- Restore the state file if it was replaced by a link during a move
- Avoid symlinked state paths; use bind mounts or direct paths instead
Example fix
# before ln -s /shared/state.json ~/.omx/state.json # after cp /shared/state.json ~/.omx/state.json
Defensive patterns
Strategy: type-guard
Validate before calling
import { lstatSync } from "node:fs";
function isRegularStateFile(path: string): boolean {
try {
const st = lstatSync(path);
return st.isFile() && !st.isSymbolicLink();
} catch {
return false;
}
} Type guard
import { Stats } from "node:fs";
function isRegularFile(stat: Stats): boolean {
return stat.isFile() && !stat.isSymbolicLink();
} Prevention
- Never symlink individual state files
- Audit state directories for links after restores or moves
- Exclude state dirs from backup tools that recreate files as links
When it happens
Trigger: A state file reference resolving to a symlink (e.g. state.json -> /etc/something), a directory, or a deleted/non-regular path. lstatSync is used deliberately so symlinks themselves are detected rather than followed.
Common situations: Users symlinking state directories between machines or into dotfiles repos; backup tools replacing files with links; state dir moved and linked back; containerized setups sharing state via links.
Related errors
- Refusing cancellation outside authorized state root: ${ref.p
- Refusing cancellation through non-regular run state target:
- Refusing to use unsafe backup ancestor ${currentPath}.
- Unsafe Autopilot context directory: .omx is a symbolic link
- Unsafe Autopilot context directory: .omx/context is a symbol
AI-assisted analysis of Yeachan-Heo/oh-my-codex@3ad79a8a6f (2026-08-27).
Data as JSON: /api/errors/36f8cb706b088def.
Report an issue: GitHub.