aaif-goose/goose · error
Editor exited with non-zero status: {}
Error message
Editor exited with non-zero status: {} What it means
goose spawns the user's $EDITOR/$VISUAL on a temp file to collect multi-line prompt input (editor.rs). After the child process exits, its exit status is checked; any non-zero exit code produces this error and the edited file is not accepted. The number in the message is the raw exit code (-1 when the process was killed by a signal).
Source
Thrown at crates/goose-cli/src/session/editor.rs:182
return Err(anyhow::anyhow!("Empty editor command"));
}
let mut cmd = Command::new(&parts[0]);
if let Ok(cwd) = std::env::current_dir() {
cmd.current_dir(cwd);
}
if parts.len() > 1 {
cmd.args(&parts[1..]);
}
cmd.arg(file_path)
.stdin(Stdio::inherit())
.stdout(Stdio::inherit())
.stderr(Stdio::inherit());
let status = cmd.status()?;
if !status.success() {
return Err(anyhow::anyhow!(
"Editor exited with non-zero status: {}",
status.code().unwrap_or(-1)
));
}
Ok(())
}
/// Main function to get input from editor
pub fn get_editor_input(
editor_cmd: &str,
messages: &[&str],
prefill: Option<&str>,
) -> Result<(String, bool)> {
let temp_file = create_temp_file(messages, prefill)?;
let temp_path = temp_file.path().to_path_buf();
let symlink_path = PathBuf::from(".goose_prompt_temp.md");View on GitHub (pinned to 3810898a74)
Solutions
- Re-open the editor and quit with a success status (vim :wq instead of :cq)
- Verify $EDITOR/$VISUAL resolves to an installed, working binary: echo $EDITOR && $EDITOR --version
- Use inline multi-line input instead of the editor in environments that cannot host one
- If the exit was an intentional abort, treat this error as a user cancellation at the call site instead of a hard failure
Example fix
// before
let text = get_editor_input(editor_cmd, &[])?;
// after
match get_editor_input(editor_cmd, &[]) {
Ok(text) => { /* use text */ }
Err(e) if e.to_string().contains("non-zero status") => return Ok(()), // user aborted
Err(e) => return Err(e),
} Defensive patterns
Strategy: try-catch
Validate before calling
use std::process::Command;
fn editor_works(editor_cmd: &str) -> bool {
let mut parts = editor_cmd.split_whitespace();
let bin = match parts.next() { Some(b) => b, None => return false };
Command::new(bin).arg("--version").output().is_ok()
} Try / catch
match get_editor_input(editor_cmd, &[]) {
Ok(text) => { /* use text */ }
Err(e) if e.to_string().contains("non-zero status") => {
// editor aborted: treat as user cancellation, not a crash
return Ok(());
}
Err(e) => return Err(e),
} Prevention
- Set EDITOR to a simple, non-blocking binary (vim, nano) in scripts and containers
- Quit editors with a success status (:wq), never :cq, when input should be kept
- Wrap editor flows so a non-zero exit maps to a cancel action rather than a fatal error
When it happens
Trigger: Any path that opens the editor for input (interactive CLI editor flow via get_editor_input / launch_editor) where the editor exits non-zero: quitting vim with :cq, an EDITOR wrapper script that exits 1, or an editor binary that crashes on startup.
Common situations: EDITOR/VISUAL pointing at a missing or broken binary; the user aborting the editor deliberately; containers/CI without a usable editor; terminal multiplexer issues breaking the spawned editor.
Related errors
- {label} subprocess exited with status {}: {}
- Invalid editor command: unmatched quotes in '{editor_cmd}'
- Empty editor command
- Job name must start with a letter or number and contain only
- --model must be in provider/model form, e.g. anthropic/claud
AI-assisted analysis of aaif-goose/goose@3810898a74 (2026-08-16).
Data as JSON: /api/errors/501368a3c4d53d54.
Report an issue: GitHub.