astrid-runtime/astrid · error

Failed to launch

Error message

Failed to launch '{editor}': {e}

What it means

Thrown by `edit_config` when spawning `$EDITOR`/`$VISUAL` (default `vi`) via `std::process::Command::status()` fails, i.e. the process could not be launched at all. This is distinct from the editor exiting non-zero (that produces 'editor ... exited with non-zero status'). Typical cause is the editor binary not existing or not being executable.

Solutions

  1. Verify the editor exists and is executable: `command -v "$EDITOR"`.
  2. Set EDITOR/VISUAL to a plain binary name on PATH, e.g. `export EDITOR=vim` (avoid aliases or argument strings).
  3. Install the configured editor or pick one present in the environment (`export VISUAL=vi`).
  4. Check the wrapped {e} for NotFound/PermissionDenied and fix PATH or chmod +x accordingly.

Example fix

// before (shell)
export EDITOR="code --wait"   # fails in headless env
astrid config edit
// after (shell)
export VISUAL=vi
export EDITOR=vi
astrid config edit
Defensive patterns

Strategy: validation

Validate before calling

let editor = std::env::var("EDITOR").or_else(|_| std::env::var("VISUAL")).unwrap_or_else(|_| "vi".into());
if which::which(&editor).is_err() {
    eprintln!("EDITOR '{editor}' not found on PATH; falling back to vi");
}

Try / catch

match Command::new(&editor).arg(&path).status() {
    Err(e) => eprintln!("cannot launch '{editor}': {e}; is it installed and on PATH?"),
    Ok(s) if !s.success() => eprintln!("editor exited with {s}"),
    Ok(_) => {},
}

Prevention

When it happens

Trigger: Running `astrid config edit` with EDITOR set to a nonexistent program, an editor not on PATH, a non-executable file, or a GUI editor invoked from a headless environment where its launch prerequisites are missing.

Common situations: EDITOR='code --wait' in a container without code installed; EDITOR set to a shell alias (aliases aren't resolved by Command::new); EDITOR contains arguments that the resolver doesn't split.

Related errors


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

Appendix: source

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

/// file if missing so the editor opens on a real path.
pub(crate) fn edit_config() -> Result<()> {
    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(),

View on GitHub (pinned to affd8760f4)