xai-org/grok-build · error

Failed to spawn ripgrep: {}

Error message

Failed to spawn ripgrep: {}

What it means

content_search_streaming builds a ripgrep command via build_ripgrep_command and spawns it as a child process. This error is thrown when std Command::spawn fails — i.e. the ripgrep binary could not be located or executed at all. The underlying io::Error is included in the message.

Source

Thrown at crates/codegen/xai-grok-workspace/src/file_system/content.rs:146

/// Streaming content search with batched status notifications. Cancellation
/// is dropping the future: the spawn config kills rg on drop.
pub async fn content_search_streaming<F>(
    root: &Path,
    params: &ContentSearchParams,
    on_status: F,
) -> anyhow::Result<ContentSearchData>
where
    F: Fn(ContentSearchBatch) + Send + 'static,
{
    let max_files = params.max_files.unwrap_or(DEFAULT_MAX_FILES);
    let max_matches = params.max_matches.unwrap_or(DEFAULT_MAX_MATCHES);

    let mut cmd = build_ripgrep_command(root, params);
    #[allow(clippy::disallowed_methods)] // waited on below; killed on drop (cancellation)
    let mut child = cmd
        .spawn()
        .map_err(|e| anyhow::anyhow!("Failed to spawn ripgrep: {}", e))?;

    let stdout = child
        .stdout
        .take()
        .ok_or_else(|| anyhow::anyhow!("Failed to capture ripgrep stdout"))?;

    let mut reader = BufReader::new(stdout).lines();
    let mut files: Vec<ContentMatchFile> = Vec::new();
    let mut current_file: Option<ContentMatchFile> = None;
    let mut total_matches = 0usize;
    let mut pending_files: Vec<ContentMatchFile> = Vec::new();
    let mut last_notify = Instant::now();
    let mut hit_limit = false;

    while let Ok(Some(line)) = reader.next_line().await {
        if line.is_empty() {
            continue;
        }

View on GitHub (pinned to bc7f02eddd)

Solutions

  1. Install ripgrep (`cargo install ripgrep`, `apt install ripgrep`, `brew install ripgrep`) or verify `rg` resolves with `which rg`.
  2. If the tooling lets you configure the rg path, point it at a valid executable and chmod +x it.
  3. Ensure the PATH seen by the process includes the directory containing rg (container/CI images often have minimal PATHs).
  4. Match the rg binary architecture/OS to the host.

Example fix

// before: fails when rg is missing
content_search_streaming(root, params).await?;
// after: fail fast with a clear prerequisite
if which::which("rg").is_err() {
    anyhow::bail!("ripgrep is required; install it or set the rg path");
}
content_search_streaming(root, params).await?;
Defensive patterns

Strategy: validation

Validate before calling

use std::process::Command;
fn ripgrep_available() -> bool {
    Command::new("rg").arg("--version").output().map(|o| o.status.success()).unwrap_or(false)
}
assert!(ripgrep_available(), "ripgrep ('rg') must be installed and on PATH");

Try / catch

match content_search_streaming(root, params).await {
    Ok(matches) => matches,
    Err(e) if e.to_string().starts_with("Failed to spawn ripgrep") => {
        eprintln!("ripgrep is not installed; run: cargo install ripgrep");
        std::process::exit(1);
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling content_search_streaming when the `rg` binary is not on PATH, the path configured for ripgrep does not exist, the binary lacks execute permission, or an exec-format/architecture mismatch occurs.

Common situations: ripgrep not installed in a container/CI image; a bundled rg path pointing at a stripped binary; permissions stripped by packaging; running on an OS/arch the rg build does not support.

Related errors


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