GitoxideLabs/gitoxide · error

Git editor exited with

Error message

Git editor {editor_display} exited with {status}

What it means

tix launches the configured Git editor (from `core.editor`/`GIT_EDITOR`) as a child process to let the user edit a commit-message document. If the editor process terminates with a non-zero exit status, the edit is treated as failed and this error is raised with the editor command and its status. The document on disk is discarded, so the operation should be retried.

Solutions

  1. Fix or replace the editor configured via `GIT_EDITOR`/`core.editor` (e.g. `git config core.editor vim`) and retry the operation.
  2. Check why the editor exits non-zero: run the same editor manually on a scratch file to reproduce and fix script errors.
  3. In non-interactive environments, use a non-interactive editor such as `GIT_EDITOR=true` or pipe the message instead of spawning an editor.
  4. Verify the editor script is executable and exits 0 on a successful save.

Example fix

// before: GIT_EDITOR points to a failing script
GIT_EDITOR=./broken-editor.sh tix reword
// error: Git editor ./broken-editor.sh exited with exit status: 1

// after: configure a working editor
export GIT_EDITOR=vim
# or for CI: export GIT_EDITOR=true
Defensive patterns

Strategy: try-catch

Validate before calling

// Rust: verify the editor is runnable before editing
let program = std::env::var("GIT_EDITOR").unwrap_or_else(|_| "vi".into());
assert!(which::which(program.split_whitespace().next().unwrap()).is_ok(),
        "editor {program} not found");

Try / catch

// Rust
match edit_document_without_terminal(editor, doc, "COMMIT_EDITMSG") {
    Ok(edited) => { /* proceed */ }
    Err(e) if e.to_string().contains("exited with") => {
        eprintln!("editor failed: {e}; fix GIT_EDITOR and retry");
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling `edit_document`/`edit_document_without_terminal` when the spawned editor command exits non-zero: the editor binary crashes, a terminal editor fails without a TTY, the user saves-and-quits with an error (e.g. vim `:cq`), or the configured editor script fails.

Common situations: `GIT_EDITOR` pointing to a missing or non-executable wrapper script; an editor like `vim` invoked with `:cq`; a GUI editor that cannot attach to the temp file; running inside an environment where the editor cannot open a terminal.

Understand the failure class

Background: "git command failed": what it means when a tool shells out to git and git exits non-zero — this error's family across 21 libraries.

Related errors


AI-assisted analysis of GitoxideLabs/gitoxide@e73179060b (2026-09-08). Data as JSON: /api/errors/3cbed9cb487413b5. Report an issue: GitHub.

Appendix: source

Thrown at gix-tix/src/edit/mod.rs:140

        gix::tempfile::ContainingDirectory::Exists,
        gix::tempfile::AutoRemove::Tempfile,
    )
    .context("could not create commit message file")?;
    tempfile
        .write_all(document)
        .context("could not write commit message file")?;
    tempfile.flush().context("could not flush commit message file")?;
    let path = tempfile
        .with_mut(|tempfile| tempfile.path().to_owned())
        .context("commit message file disappeared")?;
    let _tempfile = tempfile.close().context("could not close commit message file")?;

    let editor_display = editor.command.to_string_lossy().into_owned();
    let status = Command::from(editor.arg(&path))
        .status()
        .with_context(|| format!("could not launch Git editor {editor_display}"))?;
    if !status.success() {
        anyhow::bail!("Git editor {editor_display} exited with {status}");
    }
    let edited = std::fs::read(path).context("could not read edited commit message")?;
    Ok((edited != document).then_some(edited))
}

#[cfg(test)]
mod tests {
    use std::{path::Path, process::Command};

    use super::*;

    fn git(path: &Path, args: &[&str]) -> gix_testtools::Result<Vec<u8>> {
        let output = Command::new("git").arg("-C").arg(path).args(args).output()?;
        if !output.status.success() {
            return Err(format!(
                "git {} failed: {}",
                args.join(" "),
                String::from_utf8_lossy(&output.stderr)

View on GitHub (pinned to e73179060b)