xai-org/grok-build · error

invalid editor command

Error message

invalid editor command

What it means

A placeholder io::Error (InvalidInput, 'invalid editor command') used as the initial editor_result in run_pending_suspends when preparing the pending external editor request. It is the sentinel value that remains only if the editor launch never assigns a real result; preparation failures surface through external_editor::prepare instead.

Source

Thrown at crates/codegen/xai-grok-pager/src/app/event_loop.rs:718

    if !suspend_retry_ready(*suspend_retry_after, Instant::now()) {
        return Ok(());
    }
    // The gate is consumed before any blocking park/drain attempt
    // A timeout must arm a fresh deadline before this function returns
    if !editor_pending && !pager_pending {
        *suspend_retry_after = None;
        return Ok(());
    }
    *suspend_retry_after = None;

    // $EDITOR suspend: disable raw mode, spawn the editor, wait for exit, then restore
    // Preparation writes prompt drafts out only immediately before this safe terminal handoff
    if let Some(request) = app.pending_editor.take() {
        let retry_request = request.clone();
        match crate::app::external_editor::prepare(app, request) {
            Ok(Some(prepared)) => {
                let launch = prepared.launch();
                let mut editor_result = Err(std::io::Error::new(
                    std::io::ErrorKind::InvalidInput,
                    "invalid editor command",
                ));
                let moved_cursor = match suspend_for_child(
                    app.screen_mode,
                    terminal,
                    input_paused,
                    reader_parked,
                    input_rx,
                    || {
                        editor_result = std::process::Command::new(&launch.argv[0])
                            .args(&launch.argv[1..])
                            .arg(&launch.path)
                            .status();
                    },
                ) {
                    Ok(moved_cursor) => moved_cursor,
                    Err(error) if error.kind() == std::io::ErrorKind::TimedOut => {

View on GitHub (pinned to bc7f02eddd)

Solutions

  1. Check that the configured editor command is a non-empty, executable path (EDITOR env or config)
  2. Inspect why prepare() returned Ok(Some) with an unusable launch command
  3. Update the crate if this is a fallthrough bug (sentinel should never leak to the user)
  4. Set a valid editor and retry the editor-open action

Example fix

// before
EDITOR=""
// after
export EDITOR="vim"  # or full path: /usr/bin/vim
Defensive patterns

Strategy: validation

Validate before calling

let editor = std::env::var("EDITOR").unwrap_or_default();
if editor.trim().is_empty()
    || which::which(&editor).is_err() {
    panic!("EDITOR must be a non-empty, executable command");
}

Try / catch

match result {
  Err(e) if e.kind() == std::io::ErrorKind::InvalidInput
      && e.to_string().contains("invalid editor command") => eprintln!("fix EDITOR config"),
  ok => ok,
}

Prevention

When it happens

Trigger: Only reachable if the editor_result sentinel is never overwritten — i.e. an internal logic path where prepared.launch() / suspend_for_child fails to produce a result, or external_editor::prepare yields a launch config with an empty/invalid command.

Common situations: EDITOR/viual editor config resolving to an empty string or nonexistent binary so prepare/launch cannot form a valid command; internal fallthrough bug.

Related errors


AI-assisted analysis of xai-org/grok-build@bc7f02eddd (2026-08-31). Data as JSON: /api/errors/8969d1ff296eb93b. Report an issue: GitHub.