warpdotdev/warp · error

Failed to parse line number in Grep output: {:?}

Error message

Failed to parse line number in Grep output: {:?}

What it means

The grep output parser found a file and a second colon-separated token, but that token failed to parse as usize (a line number). The underlying ParseIntError is embedded in the message, so the offending field's content can be inferred from the failing shape.

Source

Thrown at app/src/ai/blocklist/action_model/execute/grep.rs:663

    shell_launch_data: Option<ShellLaunchData>,
    current_working_directory: Option<String>,
) -> anyhow::Result<Vec<GrepFileMatch>> {
    let mut matched_files = HashMap::new();

    for line in output.trim().split("\n") {
        let mut parts = line.split(":");
        let file = parts.next();
        let line_number = parts.next();

        let (Some(file), Some(line_number)) = (file, line_number) else {
            return Err(anyhow::anyhow!(
                "Failed to parse Grep output, unexpected format"
            ));
        };
        let line_number = match line_number.parse::<usize>() {
            Ok(line_number) => line_number,
            Err(e) => {
                return Err(anyhow::anyhow!(
                    "Failed to parse line number in Grep output: {:?}",
                    e
                ));
            }
        };

        matched_files
            .entry(file)
            .or_insert_with(Vec::new)
            .push(GrepLineMatch { line_number });
    }

    Ok(matched_files
        .into_iter()
        .map(|(file, matched_lines)| GrepFileMatch {
            file_path: host_native_absolute_path(
                file,
                &shell_launch_data,

View on GitHub (pinned to e72fd7aacb)

Solutions

  1. Always pass -n so line numbers are present, and --no-messages to suppress 'grep:' diagnostics
  2. Pre-filter lines starting with 'grep:' or lacking a numeric second field instead of hard-failing
  3. On Windows, strip or special-case the drive-letter prefix before splitting
  4. Consider a delimiter that cannot appear in the file slot, or use grep's -z/NUL output for exact splitting

Example fix

// before
let line_number = match line_number.parse::<usize>() {
    Ok(n) => n,
    Err(e) => return Err(anyhow::anyhow!("Failed to parse line number in Grep output: {:?}", e)),
};

// after
let line_number = match line_number.parse::<usize>() {
    Ok(n) => n,
    Err(_) => {
        log::warn!("Skipping grep line with non-numeric line field: {line:?}");
        continue;
    }
};
Defensive patterns

Strategy: fallback

Type guard

fn parses_as_match(line: &str) -> Option<(&str, usize)> {
    let mut p = line.splitn(3, ':');
    let f = p.next()?;
    let n = p.next()?.parse::<usize>().ok()?;
    Some((f, n))
}

Try / catch

match parse_grep_output(&output, shell, cwd).await {
    Err(e) if e.to_string().contains("Failed to parse line number") => {
        parse_lenient(&output) // skip non-numeric lines, keep the rest of the matches
    }
    r => r,
}

Prevention

When it happens

Trigger: The second ':'-separated field is not a number: Windows-style paths ('C:\Users\...' makes 'C' the file and the rest the 'line number'), grep diagnostics like 'grep: dir: No such file or directory' (file='grep', line=' dir'), or output where columns appear without -n (grep.rs:659-665).

Common situations: Running grep on Windows where the drive-letter colon shifts the fields; stderr diagnostics interleaved with matches; grep flavor that omits line numbers; filenames containing colons (e.g. timestamps).

Understand the failure class

Related errors


AI-assisted analysis of warpdotdev/warp@e72fd7aacb (2026-08-16). Data as JSON: /api/errors/ab3d0e898284dc9b. Report an issue: GitHub.