xai-org/grok-build · error

git discover task failed: {error}

Error message

git discover task failed: {error}

What it means

Git root discovery runs in a blocking task (spawn_blocking(discover_git_root)). If the tokio runtime shuts down or the task is cancelled, .await returns a JoinError, which the library wraps as "git discover task failed: {error}". This is distinct from discovery itself failing — the discovery task never delivered a result.

Source

Thrown at crates/codegen/xai-grok-workspace/src/session/git_gate.rs:641

            cached_at: Instant::now(),
        },
    );
}

fn forget_cached_roots(root: &Path) {
    ROOT_CACHE.lock().retain(|_, entry| entry.root != root);
}

async fn canonical_git_root(path: &Path) -> Result<PathBuf> {
    let cwd = dunce::canonicalize(path).unwrap_or_else(|_| path.to_path_buf());
    if let Some(root) = lookup_cached_root(&cwd) {
        return Ok(root);
    }

    let probe = cwd.clone();
    let discovered = tokio::task::spawn_blocking(move || discover_git_root(&probe))
        .await
        .map_err(|error| anyhow!("git discover task failed: {error}"))?;
    let discovered = match discovered {
        GitDiscoveryResult::Found(root) => root,
        GitDiscoveryResult::NotARepo => {
            anyhow::bail!("not a git repository: {}", path.display())
        }
        GitDiscoveryResult::DiscoveryFailed(error) => {
            return Err(error).context(format!("git discover failed for {}", path.display()));
        }
    };
    let root = dunce::canonicalize(&discovered).unwrap_or(discovered);
    store_cached_root(cwd, root.clone());
    Ok(root)
}

#[cfg(test)]
#[path = "git_gate_tests.rs"]
mod tests;

View on GitHub (pinned to bc7f02eddd)

Solutions

  1. Retry the operation on a healthy runtime — discovery is idempotent.
  2. Ensure the tokio runtime outlives all in-flight calls (keep the Runtime/Arc of the service alive until shutdown completes, await your tasks before dropping the runtime).
  3. If JoinError shows a panic, fix the panicking path in discover_git_root / guard against poisoned state.
  4. In tests, use a common runtime handle per test and shutdown_timeout so tasks are not cancelled mid-flight.

Example fix

// before
{
    let rt = tokio::runtime::Runtime::new()?;
    rt.block_on(service.discover(&path))?;
} // runtime dropped while other tasks still run -> JoinError
// after
let rt = tokio::runtime::Runtime::new()?;
rt.block_on(service.discover(&path))?;
rt.shutdown_timeout(Duration::from_secs(10)); // let in-flight tasks finish
Defensive patterns

Strategy: retry

Try / catch

// JoinError means the task never finished — safe to retry on a live runtime
match discover().await {
    Err(e) if e.to_string().contains("git discover task failed") => {
        tokio::time::sleep(Duration::from_millis(200)).await;
        discover().await
    }
    other => other,
}

Prevention

When it happens

Trigger: Calling the discovery entry point (git_gate.rs:641) while the tokio runtime is shutting down (task cancelled during drop), the runtime's blocking pool is saturated/killed, or the spawned task panics — the JoinError is then wrapped into this anyhow error.

Common situations: A server stopping while in-flight requests still attempt git discovery; tests tearing down their runtime before futures complete; blocking-pool exhaustion causing cancellation/panic in the discover task; panic inside discover_git_root (e.g. poisoned lock or unwraps) surfacing as a JoinError.

Related errors


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