xai-org/grok-build · error

grove daemon unreachable

Error message

grove daemon unreachable

What it means

cancel_worktree_create first pings the grove daemon; if the ping fails it bails with 'grove daemon unreachable' before sending the CancelWorktreeCreate RPC. This means the client cannot reach the daemon that owns in-flight worktree creations, so the cancel request was never attempted.

Source

Thrown at crates/codegen/xai-fast-worktree/src/nfs/client.rs:237

                storage_full: body.storage_full,
                unknown: false,
                mount: body.mount,
            }),
            Ok(Response::Err(e)) if e.error.contains("unknown worktree_id") => Ok(QuerySnapshot {
                phase: None,
                declined: None,
                storage_full: false,
                unknown: true,
                mount: None,
            }),
            Ok(Response::Err(e)) => Err(NfsTryError::Other(anyhow!(e.error))),
            Err(e) => Err(NfsTryError::Other(e)),
        }
    }

    pub fn cancel_worktree_create(&self, worktree_id: &str) -> Result<(), anyhow::Error> {
        if !self.ping() {
            anyhow::bail!("grove daemon unreachable");
        }
        let req = Request::CancelWorktreeCreate {
            v: PROTOCOL_VERSION,
            worktree_id: worktree_id.to_owned(),
        };
        match self.call(&req, REMOVE_RPC_TIMEOUT) {
            Ok(Response::Ok(_)) => Ok(()),
            Ok(Response::Err(e)) => Err(anyhow!(e.error)),
            Err(e) => Err(e),
        }
    }

    pub fn cleanup_worktree_create(&self, worktree_id: &str) -> Result<(), anyhow::Error> {
        if !self.ping() {
            anyhow::bail!("grove daemon unreachable");
        }
        let req = Request::CleanupWorktreeCreate {
            v: PROTOCOL_VERSION,

View on GitHub (pinned to bc7f02eddd)

Solutions

  1. Check the daemon is running and reachable: ping the configured socket/port (e.g. grove daemon status / ss -x | grep grove) and start it if stopped.
  2. Verify the socket path / address passed via NfsWorktreeOpts matches where the daemon is actually listening.
  3. Retry cancel_worktree_create with backoff — transient unreachability during daemon restart resolves itself.
  4. If the daemon is permanently gone, rely on the daemon's own journal/expiry (cleanup_worktree_create on next connect) instead of cancelling.

Example fix

// before: cancel immediately, bail on first unreachable daemon
client.cancel_worktree_create(&worktree_id)?;
// after: retry briefly before giving up
for _ in 0..5 {
    match client.cancel_worktree_create(&worktree_id) {
        Ok(()) => break,
        Err(e) if e.to_string().contains("grove daemon unreachable") => std::thread::sleep(Duration::from_millis(500)),
        Err(e) => return Err(e),
    }
}
Defensive patterns

Strategy: retry

Validate before calling

fn daemon_reachable(client: &NfsWorktreeClient) -> bool { client.ping() }

Try / catch

retry_with_backoff(5, Duration::from_millis(500), || {
    client.cancel_worktree_create(&worktree_id)
}).map_err(|e| e.context("grove daemon unreachable; cancel not delivered"))?;

Prevention

When it happens

Trigger: Calling NfsWorktreeClient::cancel_worktree_create while the grove daemon is down, restarting, listening on a different socket/port than configured, or blocked by permissions/firewall — ping() returns false and the error is raised.

Common situations: Daemon crashed or was restarted between create and cancel; stale NfsWorktreeClient constructed against an old socket path; daemon still starting during early shutdown/cleanup; container restarted and the grove socket vanished.

Related errors


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