herdrdev/herdr · error · io::Error

failed to parse editor command {editor:?}

Error message

failed to parse editor command {editor:?}

What it means

When opening scrollback in an editor on Windows, Herdr parses the EDITOR/VISUAL-style command string with command_line_to_argv (Windows command-line splitting rules). If parsing yields None — the string cannot be tokenized into an argv — this InvalidInput error reports the offending editor value.

Source

Thrown at src/platform/windows.rs:765

pub(crate) fn scrollback_editor_argv(path: &std::path::Path) -> std::io::Result<Vec<String>> {
    let editor = std::env::var("VISUAL")
        .ok()
        .filter(|value| !value.trim().is_empty())
        .or_else(|| {
            std::env::var("EDITOR")
                .ok()
                .filter(|value| !value.trim().is_empty())
        });
    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;

View on GitHub (pinned to f457cff4f2)

Solutions

  1. Fix quoting in the editor variable: ensure every opening quote has a closing partner and no stray backslash escapes a closing quote
  2. Simplify the editor command to a single unquoted executable path with no spaces if possible
  3. Quote the whole path once: EDITOR='"C:\Program Files\VS Code\bin\code.cmd"'
  4. Unset EDITOR to fall back to notepad.exe

Example fix

# before
EDITOR='"C:\\My Editor\\e.exe"'
# after
EDITOR='"C:\Program Files\MyEditor\e.exe"'
Defensive patterns

Strategy: validation

Validate before calling

fn editor_parses(editor: &str) -> bool {
    // mirror Windows rules: balanced quotes, no dangling backslash-quote
    let mut in_quotes = false;
    let chars: Vec<char> = editor.chars().collect();
    let mut i = 0;
    while i < chars.len() {
        match chars[i] {
            '"' => in_quotes = !in_quotes,
            '\\' if in_quotes && i + 1 < chars.len() && chars[i + 1] == '"' => i += 1,
            _ => {}
        }
        i += 1;
    }
    !in_quotes
}

Try / catch

Err(e) if e.kind() == std::io::ErrorKind::InvalidInput && e.to_string().contains("failed to parse editor command") => {
    // show the raw editor value to the user and fall back to notepad.exe
}

Prevention

When it happens

Trigger: Calling scrollback_editor_argv (directly or via the open-in-editor action) with an editor string that command_line_to_argv cannot parse: unbalanced quotes, trailing backslashes inside quotes, or other malformed Windows command-line quoting.

Common situations: EDITOR set to something like '"C:\\My Editor\\v.exe" -arg' with mismatched quotes; exported from a POSIX shell with escaping mangled (Git Bash/WSL exporting to Windows); trailing backslash before a closing quote.

Understand the failure class

Related errors


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