astrid-runtime/astrid · error

editor '{editor}' exited with non-zero status

Error message

editor '{editor}' exited with non-zero status

What it means

`astrid config edit` launches the user's editor (from $EDITOR/$VISUAL, defaulting to vi) on the config file and requires a zero exit status. This error is thrown when the editor process ran but returned a non-zero code, meaning the editor itself reported a problem (user abort, unsavable file, bad editor config).

Source

Thrown at crates/astrid-cli/src/commands/config.rs:75

    let home = astrid_core::dirs::AstridHome::resolve()
        .map_err(|e| anyhow::anyhow!("Failed to resolve Astrid home: {e}"))?;
    let path = home.config_path();
    if !path.exists() {
        if let Some(parent) = path.parent() {
            std::fs::create_dir_all(parent)?;
        }
        std::fs::write(&path, "# Astrid runtime configuration\n")?;
    }
    let editor = std::env::var("EDITOR")
        .ok()
        .or_else(|| std::env::var("VISUAL").ok())
        .unwrap_or_else(|| "vi".to_string());
    let status = std::process::Command::new(&editor)
        .arg(&path)
        .status()
        .map_err(|e| anyhow::anyhow!("Failed to launch '{editor}': {e}"))?;
    if !status.success() {
        anyhow::bail!("editor '{editor}' exited with non-zero status");
    }
    Ok(())
}

/// Show all config file paths that are checked.
#[expect(clippy::unnecessary_wraps)]
pub(crate) fn show_paths() -> Result<()> {
    let home = directories::BaseDirs::new().map(|d| d.home_dir().to_string_lossy().to_string());

    let workspace = std::env::current_dir()
        .ok()
        .map(|p| p.to_string_lossy().to_string());
    let astrid_home = std::env::var("ASTRID_HOME").ok();

    let paths = ResolvedConfig::config_paths_with_layout(
        home.as_deref(),
        astrid_home.as_deref(),
        workspace.as_deref(),

View on GitHub (pinned to affd8760f4)

Solutions

  1. Check what $EDITOR/$VISUAL is set to and pick a terminal editor that exits 0 on save: export EDITOR=vim (or nano) and retry.
  2. Open the config file manually at the printed path, edit it, and save.
  3. Check for write permission on the config file and fix ownership/permissions if the editor failed to save.
  4. If the editor exit is intentional-abort behavior, ignore the error — the config was not changed.

Example fix

// before
$ EDITOR=code astrid config edit  # GUI editor returns non-zero in CI
// after
$ export EDITOR=vim
$ astrid config edit  # OK
Defensive patterns

Strategy: validation

Validate before calling

// Validate the editor before launching it
fn editor_ok(editor: &str) -> bool {
    match std::process::Command::new(editor).arg("--version").status() {
        Ok(s) => s.success(),
        Err(_) => false,
    }
}

Try / catch

let status = std::process::Command::new(&editor).arg(&path).status()
    .map_err(|e| anyhow::anyhow!("Failed to launch '{editor}': {e}"))?;
if !status.success() {
    eprintln!("editor '{editor}' exited with {} (config unchanged); set $EDITOR to a terminal editor and retry",
        status.code().unwrap_or(-1));
    return Ok(()); // treat abort as no-op instead of a hard error
}

Prevention

When it happens

Trigger: Running `astrid config edit` (edit_config) where the spawned editor command exits with status != 0 — e.g. the user quits vi with :cq, nano fails to write, or the editor errors on the file.

Common situations: EDITOR set to a GUI app or a program that doesn't accept a file argument; user intentionally aborts in vi with :cq; editor lacks write permission on the config path; misconfigured editor plugin failing at startup.

Related errors


AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09). Data as JSON: /api/errors/426fab13c253d03d. Report an issue: GitHub.