{"record":{"id":"f9f539e255fc3bdf","repo":"xai-org/grok-build","slug":"failed-to-capture-ripgrep-stdout","errorCode":null,"errorMessage":"Failed to capture ripgrep stdout","messagePattern":"Failed to capture ripgrep stdout","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/codegen/xai-grok-workspace/src/file_system/content.rs","lineNumber":151,"sourceCode":"    params: &ContentSearchParams,\n    on_status: F,\n) -> anyhow::Result<ContentSearchData>\nwhere\n    F: Fn(ContentSearchBatch) + Send + 'static,\n{\n    let max_files = params.max_files.unwrap_or(DEFAULT_MAX_FILES);\n    let max_matches = params.max_matches.unwrap_or(DEFAULT_MAX_MATCHES);\n\n    let mut cmd = build_ripgrep_command(root, params);\n    #[allow(clippy::disallowed_methods)] // waited on below; killed on drop (cancellation)\n    let mut child = cmd\n        .spawn()\n        .map_err(|e| anyhow::anyhow!(\"Failed to spawn ripgrep: {}\", e))?;\n\n    let stdout = child\n        .stdout\n        .take()\n        .ok_or_else(|| anyhow::anyhow!(\"Failed to capture ripgrep stdout\"))?;\n\n    let mut reader = BufReader::new(stdout).lines();\n    let mut files: Vec<ContentMatchFile> = Vec::new();\n    let mut current_file: Option<ContentMatchFile> = None;\n    let mut total_matches = 0usize;\n    let mut pending_files: Vec<ContentMatchFile> = Vec::new();\n    let mut last_notify = Instant::now();\n    let mut hit_limit = false;\n\n    while let Ok(Some(line)) = reader.next_line().await {\n        if line.is_empty() {\n            continue;\n        }\n\n        let json: serde_json::Value = match serde_json::from_str(&line) {\n            Ok(v) => v,\n            Err(_) => continue,\n        };","sourceCodeStart":133,"sourceCodeEnd":169,"githubUrl":"https://github.com/xai-org/grok-build/blob/bc7f02eddd3d84085849dc19ed216f11c23b0571/crates/codegen/xai-grok-workspace/src/file_system/content.rs#L133-L169","documentation":"Immediately after spawning ripgrep, content_search_streaming takes ownership of the child's stdout. If stdout is somehow absent (take() returns None), this error is thrown. In practice spawn() was configured with piped stdout, so this is a defensive check that should rarely fire.","triggerScenarios":"Calling content_search_streaming when the child process was spawned without Stdio::piped() for stdout (e.g. build_ripgrep_command changed or was overridden), or a platform anomaly where the pipe could not be created.","commonSituations":"A modification to build_ripgrep_command that switched stdout to Stdio::inherit() or null; unusual sandboxed environments that deny pipe creation; forks/wrappers of the command builder.","solutions":["Inspect build_ripgrep_command and ensure it sets `.stdout(Stdio::piped())`.","Re-run — if transient (pipe creation failure), retrying usually works.","Check sandbox/SELinux/seccomp policies that may block anonymous pipes for child processes."],"exampleFix":"// before: stdout not piped\nCommand::new(\"rg\").args(&args).spawn()\n// after\nCommand::new(\"rg\").args(&args)\n    .stdout(std::process::Stdio::piped())\n    .stderr(std::process::Stdio::piped())\n    .spawn()","handlingStrategy":"try-catch","validationCode":"fn ripgrep_piped() -> bool {\n    std::process::Command::new(\"rg\")\n        .arg(\"--version\")\n        .stdout(std::process::Stdio::piped())\n        .output()\n        .map(|o| o.status.success())\n        .unwrap_or(false)\n}","typeGuard":null,"tryCatchPattern":"match content_search_streaming(root, params).await {\n    Ok(m) => m,\n    Err(e) if e.to_string() == \"Failed to capture ripgrep stdout\" => {\n        eprintln!(\"internal error: ripgrep stdout not piped; check build_ripgrep_command\");\n        fallback_search(root, params)\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Never modify build_ripgrep_command to drop Stdio::piped() on stdout","Add a unit test asserting the child's stdout is piped before reading","Keep a non-streaming fallback search path for degraded environments"],"tags":["ripgrep","process-spawn","io","internal-invariant"],"backgroundTag":"missing-process-stdout","analyzedSha":"bc7f02eddd3d84085849dc19ed216f11c23b0571","analyzedAt":"2026-08-31T04:59:42.031Z","schemaVersion":2},"datasetVersion":"2026-08-31T09:17:48.483Z"}