herdrdev/herdr · error · io::Error

editor command must not be empty

Error message

editor command must not be empty

What it means

After parsing the editor command on Windows, Herdr rejects an argv that tokenized to zero arguments. This happens when the editor setting is non-empty per the trim check but the parser produces no tokens (e.g. a string of only quotes or whitespace-like characters that pass trim but split to nothing).

Source

Thrown at src/platform/windows.rs:773

        });
    scrollback_editor_argv_with_env(path, editor.as_deref())
}

fn scrollback_editor_argv_with_env(
    path: &std::path::Path,
    editor: Option<&str>,
) -> std::io::Result<Vec<String>> {
    let mut argv = match editor.filter(|value| !value.trim().is_empty()) {
        Some(editor) => command_line_to_argv(editor).ok_or_else(|| {
            std::io::Error::new(
                std::io::ErrorKind::InvalidInput,
                format!("failed to parse editor command {editor:?}"),
            )
        })?,
        None => vec!["notepad.exe".to_string()],
    };
    if argv.is_empty() {
        return Err(std::io::Error::new(
            std::io::ErrorKind::InvalidInput,
            "editor command must not be empty",
        ));
    }
    argv.push(path.display().to_string());
    Ok(argv)
}

pub(crate) fn configure_background_command_platform(command: &mut std::process::Command) {
    use std::os::windows::process::CommandExt;

    command.creation_flags(CREATE_NO_WINDOW);
}

pub fn launch_server_daemon_command(command: &mut std::process::Command) -> std::io::Result<u32> {
    if current_job_kills_processes_on_close()? {
        launch_server_daemon_with_wmi(command)
    } else {

View on GitHub (pinned to f457cff4f2)

Solutions

  1. Print the editor variable to inspect it: echo "[$EDITOR]" | cat -A to reveal stray characters
  2. Set EDITOR to a real command like 'code --wait' or 'notepad.exe', or unset it entirely
  3. Re-export the variable from a clean shell profile without wrapping artifacts

Example fix

# before
export EDITOR='""'
# after
export EDITOR="notepad.exe"
Defensive patterns

Strategy: validation

Validate before calling

let trimmed = editor.trim();
let meaningful = trimmed.chars().any(|c| c != '"' && c != '\'');
if trimmed.is_empty() || !meaningful {
    // skip custom editor, use the default, before calling the API
}

Try / catch

Err(e) if e.kind() == std::io::ErrorKind::InvalidInput && e.to_string() == "editor command must not be empty" => {
    // treat as unset: fall back to notepad.exe
}

Prevention

When it happens

Trigger: Calling scrollback_editor_argv_with_env with an editor value that passes the !trim().is_empty() guard yet parses to an empty argv — for example a value of just '""' or characters the splitter drops entirely.

Common situations: EDITOR accidentally set to quote characters or invisible characters via a broken export in a shell profile; CI environments setting EDITOR='' with stray quotes; scripts writing an editor variable with formatting bugs.

Related errors


AI-assisted analysis of herdrdev/herdr@f457cff4f2 (2026-08-28). Data as JSON: /api/errors/569d0656f2543234. Report an issue: GitHub.