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
- Check that the configured editor command is a non-empty, executable path (EDITOR env or config)
- Inspect why prepare() returned Ok(Some) with an unusable launch command
- Update the crate if this is a fallthrough bug (sentinel should never leak to the user)
- 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
- Set EDITOR (or the config field) to a non-empty, absolute executable path
- Verify the editor binary exists with `command -v $EDITOR`
- Report to maintainers if this sentinel error ever surfaces — it should be internal only
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
- Failed to load config: {e}
- terminal writer thread exited
- {error}
- Session does not exist locally (session registry is disabled
- The change was applied, but Doctor still reports `{}`.
AI-assisted analysis of xai-org/grok-build@bc7f02eddd (2026-08-31).
Data as JSON: /api/errors/8969d1ff296eb93b.
Report an issue: GitHub.