Yeachan-Heo/oh-my-codex · error · Error
editor exited with status ${result.status ?? 'unknown'}
Error message
editor exited with status ${result.status ?? 'unknown'} What it means
editNativeAgent spawns $EDITOR (spawnSync with shell) on the agent TOML and requires exit status 0. A non-zero, null (killed by signal), or unknown status produces this error. The editor is expected to be found via PATH and env is inherited.
Source
Thrown at src/cli/agents.ts:223
function ensureInteractiveRemove(force: boolean): void {
if (force) return;
if (process.stdin.isTTY && process.stdout.isTTY) return;
throw new Error('remove requires an interactive terminal; rerun with --force in non-interactive environments');
}
async function editNativeAgent(
name: string,
options: { cwd?: string; scope?: AgentScope; editor?: string } = {},
): Promise<string> {
const path = resolveExistingAgentPath(name, options);
const editor = options.editor ?? process.env.EDITOR ?? process.env.VISUAL ?? 'vi';
const result = spawnSync(editor, [path], {
stdio: 'inherit',
shell: true,
env: process.env,
});
if (result.status !== 0) {
throw new Error(`editor exited with status ${result.status ?? 'unknown'}`);
}
return path;
}
async function removeNativeAgent(
name: string,
options: { cwd?: string; scope?: AgentScope; force?: boolean } = {},
): Promise<string> {
ensureInteractiveRemove(Boolean(options.force));
const path = resolveExistingAgentPath(name, options);
if (!options.force) {
const confirmed = await confirmRemove(path);
if (!confirmed) {
throw new Error('remove aborted by user (pass --force to skip confirmation)');
}
}
await rm(path, { force: true });
return path;View on GitHub (pinned to 3ad79a8a6f)
Solutions
- Verify $EDITOR is installed and on PATH (echo $EDITOR; command -v $EDITOR)
- Exit the editor cleanly (avoid :cq in vim)
- Set EDITOR to a simple binary name or valid shell command string
Example fix
# before EDITOR=nonexistent-edi omx agent edit reviewer # after export EDITOR=vim omx agent edit reviewer
Defensive patterns
Strategy: validation
Validate before calling
import { commandExistsSync } from 'command-exists';
const editor = process.env.EDITOR ?? 'vi';
if (!commandExistsSync(editor.split(' ')[0])) {
console.error(`editor not found: ${editor}`);
process.exit(2);
} Try / catch
try {
await editNativeAgent(name);
} catch (e) {
if (e instanceof Error && /editor exited with status/.test(e.message)) {
// fall back to printing the path so the user can edit manually
console.log(`edit manually: ${agentPath}`);
} else throw e;
} Prevention
- Set EDITOR to an installed binary in ~/.bashrc / CI env
- Exit editors cleanly (avoid vim's :cq)
- Prefer non-interactive flows (write the TOML programmatically) in automation
When it happens
Trigger: EDITOR set to a non-existent binary, editor exiting non-zero (vim :cq), editor killed by a signal, or EDITOR containing arguments that the shell mangles.
Common situations: EDITOR unset and no sane default, EDITOR='code --wait' quirks, exiting vim with an error code, or containers without editors installed.
Related errors
- stderr || `git ${args.join(' ')} failed`
- agent name must not be empty
- invalid agent name: ${name}
- \"${trimmed}\" is reserved by Codex built-in agents
- Expected --scope user|project
AI-assisted analysis of Yeachan-Heo/oh-my-codex@3ad79a8a6f (2026-08-27).
Data as JSON: /api/errors/1ce1c6f3a592e719.
Report an issue: GitHub.